How to cleanup all unused screens? - linux

I would like to remove from my systems all screens I've opened to do my tasks. But I need to get rid of the screens that aren't doing anything. I don't want to kill a screen that something happens inside.
As an example, I run a long command in one screen called screen3 while screens named screen1 and screen2 are previous screens, no jobs are running inside them. The goal is to have a command or script (in crontab) that automatically clean user1 and user2.

First attempt - detection only
screen -wipe > /dev/null
screen_pids=$(screen -ls | grep Detached | awk '/\.*\t/ {print strtonum($1)}')
for scr_pid in $screen_pids
do
bash_child=$(ps -el | grep $scr_pid | grep bash | awk '{print $4}')
if [ $(pgrep -P $bash_child | wc -l) -eq "0" ]; then
# in that case screen $scr_pid could be killed
echo "The screen $scr_pid doesn't have any child process and should be terminated"
fi
done

Related

Multiple PIDs being stored in PID file

I have a System V init script I've developed that starts a Java program. For some reason whenever the PID file gets created, it contains multiple PIDs instead of one.
Here's the relevant code that starts the service and writes to the PID file:
daemon --pidfile=$pidfile "$JAVA_CMD &" >> $logfile 2>&1
RETVAL=$?
usleep 500000
if [ $RETVAL -eq 0 ]; then
touch "$lock"
PID=$(ps aux | grep -vE 'grep|runuser|bash' | grep <myservice> | awk '{print $2}')
echo $PID > $pidfile
When I test the ps aux... command manually, a single line returns. When running as a script, it appears that this call is returning multiple PIDs.
Example contents in the PID file: 16601 16602 16609 16619 16690. 16619 is the actual process ID found when manually running the ps aux... command mentioned above.
Try reversing your greps. The first one (-vE) may run BEFORE the myservice one starts up. Grep for your service FIRST, then filter out the unwanted lines:
PID=$(ps aux | grep <myservice> | grep -vE 'grep|runuser|bash' | awk '{print $2}')
I encounted the same issue but not the same statement, it was like this:
PID="$(ps -ef|grep command|grep options|grep -v grep|awk '{print $2}')"
in which I used the same grep order as #Marc said in first answer, but did not filter all the unwanted lines.
So I tried the below one and it worked:
PID="$(ps -ef|grep command|grep options|grep -vE 'grep|runuser|bash'|awk '{print $2}')"

Can i wait for a process termination that is not a child of current shell terminal?

I have a script that has to kill a certain number of times a resource managed by a high avialability middelware. It basically checks whether the resource is running and kills it afterwards, i need the timestamp of when the proc is really killed. So i have done this code:
#!/bin/bash
echo "$(date +"%T,%N") :New measures Run" > /home/hassan/logs/measures.log
for i in {1..50}
do
echo "Iteration: $i"
PID=`ps -ef | grep "/home/hassan/Desktop/pcmAppBin pacemaker_app/MainController"|grep -v "grep" | awk {'print$2'}`
if [ -n "$PID" ]; then
echo "$(date +"%T,%N") :Killing $PID" >> /home/hassan/logs/measures.log
ps -ef | grep "/home/hassan/Desktop/pcmAppBin pacemaker_app/MainController"|grep -v "grep" | awk {'print "kill -9 " $2'} | sh
wait $PID
else
PID=`ps -ef | grep "/home/hassan/Desktop/pcmAppBin pacemaker_app/MainController"|grep -v "grep" | awk {'print$2'}`
until [ -n "$PID" ]; do
sleep 2
PID=`ps -ef | grep "/home/hassan/Desktop/pcmAppBin pacemaker_app/MainController"|grep -v "grep" | awk {'print$2'}`
done
fi
done
But with my wait command i get the following error message: wait: pid xxxx is not a child of this shell
I assume that You started the child processes from bash and then start this script to wait for. The problem is that the child processes are not the children of the bash running the script, but the children of its parent!
If You want to launch a script inside the the current bash You should start with ..
An example. You start a vim and then You make is stop pressing ^Z (later you can use fg to get back to vim). Then You can get the list of jobs by using the˙jobs command.
$ jobs
[1]+ Stopped vim myfile
Then You can create a script called test.sh containing just one command, called jobs. Add execute right (e.g. chmod 700 test.sh), then start it:
$ cat test.sh
jobs
~/dev/fi [3:1]$ ./test.sh
~/dev/fi [3:1]$ . ./test.sh
[1]+ Stopped vim myfile
As the first version creates a new bash session no jobs are listed. But using . the script runs in the present bash script having exactly one chold process (namely vim). So launch the script above using the . so no child bash will be created.
Be aware that defining any variables or changing directory (and a lot more) will affect to your environment! E.g. PID will be visible by the calling bash!
Comments:
Do not use ...|grep ...|grep -v ... |awk --- pipe snakes! Use ...|awk... instead!
In most Linux-es you can use something like this ps -o pid= -C pcmAppBin to get just the pid, so the complete pipe can be avoided.
To call an external program from awk you could try system("mycmd"); built-in
I hope this helps a bit!

How to terminate a job dispatcher in back ground in Linux?

I have a job dispatcher bash shell script containing below codes:
for (( i=0; i<$toBeDoneNum; i=i+1 ))
do
while true
do
processNum=`ps aux | grep Checking | wc -l`
if [ $processNum -lt $maxProcessNum ]; then
break
fi
echo "Too many processes: Max process is $maxProcessNum."
sleep $sleepSec
done
java -classpath ".:./conf:./lib/*" odx.comm.cwv.main.Checking $i
done
I run the script like this to be in the background:
./dispatcher.sh &
I want to terminate this dispatcher process with kill -9. But I didn't record the pid of the dispatcher process at the first time. Instead I used jobs to show all the process but it shows nothing. Even this fg cannot bring the process to foreground.
fg
bash: fg: current: no such job
But I think this dispatcher process is still running because it still continues to assign java program to run. How should I terminate this job dispatcher bash shell script process?
Edit: I used jobs, jobs -l, jobs -r and jobs -s. Nothing showed.
create test.sh with content
sleep 60
then
jobs -l | grep 'test.sh &' | grep -v grep | awk '{print $2}'
this gives me the process id on Ubuntu and OSX
you can assign it to a variable and then kill it
pid=`jobs -l | grep 'test.sh &' | grep -v grep | awk '{print $2}'`
kill -9 $pid

How to check which program runs inside gnome-terminal

I want to write a program which prints the current focused window name and if it is a gnome-terminal, then prints out the running program inside the current gnome-terminal tab (for example vim, if a vim session is running).
To get the currently focused window name, I used:
xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)"
xprop -id 0x220ad5a | grep "WM_CLASS(STRING)"
If the current window is a gnome-terminal, this will return 'gnome-terminal'.
But how can I find out the program running inside gnome-terminal (more precisely: inside the current gnome-terminal tab)? I thought about using dbus but gnome-terminal does not seem to support it.
I needed to solve the same problem and after some investigation I discovered
that wmctrl and pstree prints processes in the same order.
DISCLAIMER: I'm not sure this is always the case but in my case where I use this method to open up a "cheatsheet" for manual review a problem with it would be detected immediately and so for had no problem.
Here is a demo-script that when run will output the correct row of the pstree that corresponds to the currently active terminal window. For debugging it prints intermediate steps into ~/debug.txt
#!/bin/bash
winid=$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW)/ {print $NF}' | xargs printf "%#010x\n")
echo 'winid:'$winid >> ~/debug.txt
winclass=$(xprop -id $winid | awk '/WM_CLASS/ {print $NF}')
niceclass=${winclass//\"/}
echo 'winclass:'$niceclass >> ~/debug.txt
if [ $niceclass == "Gnome-terminal" ]
then
terminalPID=$(xprop -id $winid | awk '/_NET_WM_PID/ {print $NF}')
echo 'winPID:'$terminalPID >> ~/debug.txt
# get inx of window for this PID
termInx=$(wmctrl -l -p | grep $terminalPID | awk '/'"$winid"'/ {print NR}')
echo 'term inx:'$termInx >> ~/debug.txt
# Take the childprocess of that inx and PID
shell_process=$(pstree -p $terminalPID | sed "s/.*(1998)//" | sed "s/\W*//" | awk 'NR=='$termInx)
pstree -p $terminalPID >> ~/debug.txt
echo 'found process:'$shell_process >> ~/debug.txt
echo 'found process:'$shell_process
fi
Expected output:
tony#tony-mini:~$ ./test_so.sh
found process:bash(8001)---test_so.sh(9869)---test_so.sh(9885)-+-awk(9889)
Then pick out the desired child.
Get the gnome terminal PID, and check which processes have this number as PPID.
I have answered a very similar question few days ago, see this link for details.
Thanks Adam! I am almost there. With xprop I can get the PID of the gnome-terminal (6736). But unfortunately, there is only one process for all gnome-terminal windows and tabs. See this pstree output with two opened gnome-terminal windows:
-gnome-terminal(6736)-+-bash(6738)---vim(6780)
| |-bash(7026)---pstree(7045)
| | `-{gnome-terminal}(6740)
Is there a way to find out the bash pid of the currently opened gnome-terminal tab?

Monitoring bash script won't terminate

I have this bash script whose job is to monitor a log file for the occurrence of a certain line. When located, the script will send out an email warning and then terminate itself. For some reason, it keeps on running. How can I be sure to terminate bash script below:
#!/bin/sh
tail -n 0 -f output.err | grep --line-buffered "Exception" | while read line
do
echo "An exception has been detected!" | mail -s "ALERT" monitor#company.com
exit 0
done
You are opening a subshell in the while read and that subshell is who is exiting, not the proper one.
Try before entering the while loop:
SHELLPID=$$
And then in the loop:
kill $SHELLPID
exit 0
Or change your loop to not use a subshell.
Since the parent script is always going to be in the tail -f which never ends I think you have no other choice than killing it from the inner subshell.
Try something like this:
tail -n 0 -f output.err | grep --line-buffered "Exception" | while read line
do
echo "An exception has been detected!" | mail -s "ALERT" monitor#company.com
kill -term `ps ax | grep tail | grep output.err | awk '{print $1}'`
done
This should work, provided you have only one tail keeping an eye on this particular file.

Resources