How to get the session numbers of every vncviewer background process and store them inside different variables - bash

I like to play with the bhyve virtual machines in FreeBSD a lot. As you probably know,sometime when the OS loaded by the virtual machine is halted,the process of the virtual machine is not killed. This is not a bug,but the developers say that it is like this to speed up the booting process of the virtual machines. Now,I would like to create a script to kill the "dead" virtual machines that are still listed when I do a "ps ax | grep bhyve",but that can't be used anymore. Let's take the example below :
mario#marietto:/home/marietto # ps ax | grep bhyve
13720 - Is 0:00.00 bhyve: system.pwd (bhyve)
13721 - Is 0:00.00 bhyve: system.grp (bhyve)
13831 - Ss 0:00.00 bhyve: system.pwd (bhyve)
13832 - Ss 0:00.00 bhyve: system.grp (bhyve)
13826 4 SC+ 0:17.34 bhyve: vm2 (bhyve)
13715 1 IC+ 1:00.55 bhyve: vm4 (bhyve)
13852 3 S+ 0:00.00 grep bhyve
in this case I have two virtual machines called vm2 and vm4,that became ghosts because the os inside of them has been halted. To be clear,I want to show you how is the script that I usually use to launch a bhyve vm :
bhyve -S -c sockets=2,cores=2,threads=2 -m 8G -w -H -A \
-s 0,hostbridge \
-s 1,nvme,/dev/nvd0,bootindex=1 \
-s 2,virtio-blk,/dev/$vmdisk4 \
-s 3,virtio-blk,/dev/$vmdisk8 \
-s 4,virtio-blk,/dev/$vmdisk11 \
-s 10,virtio-net,tap2 \
-s 11,virtio-9p,sharename=/ \
-s 12,hda,play=/dev/dsp,rec=/dev/dsp \
-s 29,fbuf,tcp=0.0.0.0:5902,w=1600,h=950 \
-s 30,xhci,tablet \
-s 31,lpc \
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_CODE.fd \
vm2 < /dev/null & sleep 2 && vncviewer 0:2
now,since there isn't any easy method to know if a virtual machine is a ghost or if it is running,I've thought to a system like this :
mario#marietto:/home/marietto # ps ax | grep vnc
13841 4 S+ 0:00.03 vncviewer 0:2
13727 1 S+ 0:00.04 vncviewer 0:4
13854 3 S+ 0:00.00 grep vnc
grepping the vncviewer session number is the most secure method to determine which virtual machine is really running because while a virtual machine is running really,I never close the vncviewer window but I minimize its window,and since I've associated the same number to the virtual machine and to the vncviewer session,I'm sure that the vm2 and vm4 are still running. When I will halt the vm2 and the vm4,the corresponding vnc sessions should be closed for sure. Now,what I want to do is to create a script that as output is able to give me 2 and 4,in that case. So,the script should assign the number 2 to the first variable and the number 4 to the second one :
$runvm1 = 2
$rvnvm2 = 4
Later I will complete the script like this :
bhyvectl --vm=$runvm1 --force-reset
bhyvectl --vm=$runvm1 --destroy
bhyvectl --vm=$runvm2 --force-reset
bhyvectl --vm=$runvm2 --destroy
because I want to reset and destroy all the ghost virtual machines that are still visible between the process listed with :
mario#marietto:/home/marietto # ps ax | grep bhyve

This will get your values.
#!/bin/sh
BASE=`basename "$0" ".sh" `
TMP="/tmp/tmp.$$.${BASE}"
echo "
mario#marietto:/home/marietto # ps ax | grep bhyve
13720 - Is 0:00.00 bhyve: system.pwd (bhyve)
13721 - Is 0:00.00 bhyve: system.grp (bhyve)
13831 - Ss 0:00.00 bhyve: system.pwd (bhyve)
13832 - Ss 0:00.00 bhyve: system.grp (bhyve)
13826 4 SC+ 0:17.34 bhyve: vm2 (bhyve)
13715 1 IC+ 1:00.55 bhyve: vm4 (bhyve)
13799 8 IC+ 1:00.55 bhyve: abc_vm4 (bhyve)
13852 3 S+ 0:00.00 grep bhyve
" >${TMP}.testinput
cat "${TMP}.testinput" | grep '(bhyve)' |
awk '{
if( $6 ~ /^vm/ ){
id=substr( $6, 3 ) ;
printf("%s|%s|%s\n", id, $6, $1 ) ;
} ;
### Sample output:
### 2|vm2|13826
### 4|vm4|13715
}' |
awk -F \| 'BEGIN{ indx=0 ; }{
indx++
printf("runvm"indx" = %s\n", $1 ) ;
### Sample output:
### runvm1 = 2
### runvm2 = 4
}'

Related

ps -ef | { head -n 1 ; sort ; } Unexpected output [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Why does the following cut out the word root on the second line and skew the output, not to be uniform to all the following lines?
# ps -ef | { head -n 1 ; sort ; } | head -n11
UID PID PPID C STIME TTY TIME CMD
470 2 0 Oct07 ? 00:00:00 [xfsaild/nvme4n1]
apache 10210 5801 0 Oct12 ? 00:04:04 /var/site/fastcgi.pl
apache 10211 5801 0 Oct12 ? 00:03:11 /var/site/fastcgi.pl
apache 10212 5801 0 Oct12 ? 00:03:35 /var/site/fastcgi.pl
apache 10265 5801 0 Oct12 ? 00:03:55 /var/site/fastcgi.pl
apache 10325 5801 0 Oct12 ? 00:03:50 /var/site/fastcgi.pl
apache 10328 5801 0 Oct12 ? 00:03:39 /var/site/fastcgi.pl
apache 10329 5801 0 Oct12 ? 00:02:59 /var/site/fastcgi.pl
apache 10330 5801 0 Oct12 ? 00:03:50 /var/site/fastcgi.pl
apache 11889 3815 0 Oct08 ? 00:33:11 /usr/sbin/httpd -k start
I'd expect output to print:
# ps -ef | { head -n 1 ; sort ; } | head -n2
UID PID PPID C STIME TTY TIME CMD
root 470 2 0 Oct07 ? 00:00:00 [xfsaild/nvme4n1]
This seems to be a Race condition. Sometimes when I run it it does not happen.
$ ps -ef | { head -n 1 ; sort ; } | head -n3
UID PID PPID C STIME TTY TIME CMD
avahi 1328 1 0 Oct12 ? 00:00:08 avahi-daemon: running [danied.local]
avahi 1401 1328 0 Oct12 ? 00:00:00 avahi-daemon: chroot helper
Your command is subject to race conditions, more specifically head -n1 could close the pipe behind before the second command manages to get any input, if the first command also has ended.
Consider this example:
> cat test.sh
for ((i=1;i<=3; i++)); do
printf "$i\n"
# sleep 1
done
If you run this many times, you will get different results
> sh test.sh | { head -n1; tail -n +1; }
1
> sh test.sh | { head -n1; tail -n +1; }
1
2
3
If you uncomment the sleep 1 statement into the loop, both commands will get input. Because the pipe will not be closed from the first command immediately, so the second part will wait for sure, although the first head is done.
When I launch this command, this is what I get:
Prompt> ps -ef | { head -n 1 ; sort ; } | head -n11
UID PID PPID C STIME TTY TIME CMD
Prompt> uname -a
Linux ...-Microsoft #488-Microsoft Mon Sep 01 13:43:00 ... GNU/Linux
This makes a lot more sense: ps -ef shows all running processes, head -n 1 only shows the first line, and the rest is not important.
Can you run that command again and see that everything is like you say, and run the uname -a command, in order to verify which type of machine you're working with? (The result of env | grep -i "shell" might be useful too). Just edit your question accordingly.

How to assure the selection of an open port in shell

So I have a script that creates a tunnel. To do that it uses random ports.
This is the logic for random port generation
RPORT=1
while [ $RPORT -lt 2000 ]
do
RPORT=$[($RANDOM % 3000) + 1]
done
This is good only if the port that it selects isn't in use. If that port is active, I am unable to access that server while that port is being used.
I want to do something like this
while [netsat -nat | grep $RPORT] = true
do
RPORT=$[($RANDOM % 3000) + 1]
So I want to check first if that port is in use, if so, search for another random port, check if it is in use, if no then use it.
Thank you very much in advance for you time and help!
function random_unused_port {
(netstat --listening --all --tcp --numeric |
sed '1,2d; s/[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*:\([0-9]*\)[[:space:]]*.*/\1/g' |
sort -n | uniq; seq 1 1000; seq 1 65535
) | sort -n | uniq -u | shuf -n 1
}
RANDOM_PORT=$(random_unused_port)
This was the function that helped me out!
Thank you Nahuel Fouilleul for the link!
To fix the answer, also because port from 1 to 1000 are reserved seq starts at 1001
grep -F -x -v -f <(
netstat --listening --all --tcp --numeric |
sed '1,2d; s/[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*:\([0-9]*\)[[:space:]]*.*/\1/g' |
sort -nu
) <(seq 1001 65536) | shuf -n 1

Grep the process using shell script

I want to pass the output of the sql query to aix command, later the command should grep the processes until the condition met:
SAMPLE QUERY:
SQL> select vp.spid,vs.process,to_char(logon_time,'DD-MON-YYYY HH24:MI:SS') Logon_Time
2 from v$process vp, v$session vs
3 where
4 vp.addr = vs.paddr and
5 vs.process in
(select Process
6 7 from v$session where username in ('SYS','SYSTEM','OPS$ORACLE')
8 and logon_time >= sysdate-0.010416667
9 and upper(Program) not like 'ORAAGENT%'
10 and upper(Program) not like 'EMAGENT%'
11 and upper(Program) not like 'RMAN%'
and upper(Program) not like 'OMS%'
12 13 and upper(Program) not like 'YRSUPP%');
OUTPUT:
SPID PROCESS LOGON_TIME
------------------------ ------------------------ --------------------
18022440 22872252 27-SEP-2013 11:18:01
GREP COMMAND SHOULD BE PROCESSED UNTIL $8 VALUE IS EQUAL TO SSHD: THEN SWITCH TO LSOF -I COMMAND:
SQL> !ps -ef|grep 22872252
oracle 18022440 22872252 0 11:18:01 - 0:00 oracleDSPD21 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle 20119722 22872252 0 11:41:32 pts/1 0:00 grep 22872252
oracle 22872252 30605374 0 11:18:01 pts/1 0:00 sqlplus
SQL> !ps -ef|grep 30605374
oracle 20643994 22872252 0 11:41:51 pts/1 0:00 grep 30605374
oracle 22872252 30605374 1 11:18:01 pts/1 0:00 sqlplus
oracle 30605374 11993194 0 11:07:31 pts/1 0:00 -ksh
SQL> !ps -ef|grep 11993194
root 11993194 15925354 0 11:07:31 pts/1 0:00 sudo su - oracle
oracle 19791924 22872252 0 11:42:08 pts/1 0:00 grep 11993194
oracle 30605374 11993194 0 11:07:31 pts/1 0:00 -ksh
SQL> !ps -ef|grep 15925354
oracle 10092584 22872252 0 11:42:29 pts/1 0:00 grep 15925354
root 11993194 15925354 0 11:07:31 pts/1 0:00 sudo su - oracle
l061749 15925354 11075676 0 11:07:27 pts/1 0:00 -ksh
HERE I GOT SSHD:
SQL> !ps -ef|grep 11075676
l061749 11075676 20447276 0 11:07:27 - 0:00 sshd: l061749#pts/1
l061749 15925354 11075676 0 11:07:27 pts/1 0:00 -ksh
oracle 20250734 22872252 0 11:42:57 pts/1 0:00 grep 11075676
FOR THE SSHD PROCESS NEED TO USE BELOW COMMAND:
SQL> !lsof -i|grep 11075676
lsof: WARNING: can't open /home/oracle/.lsof_ohpr420: Permission denied
sshd 11075676 l061749 3u IPv4 0xf1000e0007dcb3b8 0t50893 TCP ohpr420.rcc.nsw.westpac.com.au:ssh->10.120.119.76:egptlm (ESTABLISHED)
FROM THIS GREP THE IP ADDRESS:
SQL> !lsof -i|grep 20447276
lsof: WARNING: can't open /home/oracle/.lsof_ohpr420: Permission denied
sshd 20447276 root 3u IPv4 0xf1000e0007dcb3b8 0t51813 TCP ohpr420.rcc.nsw.westpac.com.au:ssh->10.120.119.76:egptlm (ESTABLISHED)
PLEASE DO THE NEEDFUL.
THANKS AND REGARDS
SURESH
On AIX, the lsof command must be run by root, otherwise you will get the "Permission denied" message.
Good article which uses the lsof command. "Who's using my port? (AIX, Linux, Windows example)" from http://www-01.ibm.com/support/docview.wss?uid=swg21264632

What do I do instead of grep'ing the output of ps?

Everyone knows how annoying this is:
[mybox:~ #] ps aux | grep myservice
root 2273 0.0 0.0 4360 760 ? Ss 18:06 0:00 /usr/sbin/myservice
root 18590 0.0 0.0 4100 788 pts/2 S+ 21:21 0:00 grep myservice
you get the processes you were looking for, plus the grep. So, ok you could do:
[mybox:~ #] ps aux | grep myservice | grep -v grep
root 2273 0.0 0.0 4360 760 ? Ss 18:06 0:00 /usr/sbin/myservice
or
[mybox:~ #] pgrep myservice
2273
but the former is 3 whole commands, and the latter only gets you the process id. Is there some nicer alternative?
If you now the full name of the process
ps -F -C myservice
But it wouldn't work with myserv of 'myserv*'
If you know only a partial one, you can reduce your commands to 2:
ps aux | grep [m]yserv
How about storing the piped commands into a small bash shell that takes a positional parameter? This would reduce keystrokes if that is the goal.
[mybox:~ #] cat mycmd
#!/bin/bash
ps aux | grep $1 | grep -v grep
Which could be called:
[mybox:~ #] mycmd myservice
root 2273 0.0 0.0 4360 760 ? Ss 18:06 0:00 /usr/sbin/myservice
ps + pgrep maybe?
$ ps -fp $(pgrep myservice)
UID PID PPID C STIME TTY TIME CMD
user 5422 5315 0 15:37 ? 00:00:04 /usr/bin/myservice

Can't get correct output from command `ps -eaf | grep groovy` using groovy

If I use shell:
ps -eaf | grep groovy
I can get such output:
[root#test www]# ps -eaf | grep groovy
root 924 539 1 03:15 pts/0 00:00:05 /usr/java/jdk1.6.0_31/bin/java -classpath
/root/dev/groovy-1.8.8/lib/groovy-1.8.8.jar -Dscript.name=./groovysh -Dprogram.name=groovysh
-Dgroovy.starter.conf=/root/dev/groovy-1.8.8/conf/groovy-starter.conf
-Dgroovy.home=/root/dev/groovy-1.8.8 -Dtools.jar=/usr/java/jdk1.6.0_31/lib/tools.jar
org.codehaus.groovy.tools.GroovyStarter --main org.codehaus.groovy.tools.shell.Main
--conf /root/dev/groovy-1.8.8/conf/groovy-starter.conf --classpath .
root 1127 562 0 03:20 pts/1 00:00:00 grep groovy
[root#test www]#
But if I run this command in groovy:
proc = "ps -eaf | grep groovy".execute()
proc.waitFor() // => return 1
proc.in.text // => return ""
proc.err.text // => see following
The proc.err.text will be the document of ps command:
ERROR: Garbage option.
********* simple selection ********* ********* selection by list *********
-A all processes -C by command name
-N negate selection -G by real group ID (supports names)
-a all w/ tty except session leaders -U by real user ID (supports names)
-d all except session leaders -g by session OR by effective group name
-e all processes -p by process ID
T all processes on this terminal -s processes in the sessions given
But if I run ps -eaf it will be correct.
It seems | can't be used, is it true? How to fix it?
Yeah, you can't use shell output piping and redirection like that.
One option is to do:
Process ps = 'ps -eaf'.execute()
Process gr = 'grep groovy'.execute()
Process all = ps | gr
println all.text
The other is to wrap it in a new shell using the List form of execute:
println( [ 'sh', '-c', 'ps -eaf | grep groovy' ].execute().text )

Resources