How to terminate a job dispatcher in back ground in Linux? - 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

Related

how can I kill a process in a shell script

My bash script has:
ps aux | grep foo.jar | grep -v grep | awk '{print $2}' | xargs kill
However, I get the following when running:
usage: kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
Any ideas, how to fix this line?
In general, your command is correct. If a foo.jar process is running, its PID will be passed to kill and (should) terminate.
Since you're getting kill's usage as output, it means you're actually calling kill with no arguments (try just running kill on its own, you'll see the same message). That means that there's no output in the pipeline actually reaching xargs, which in turn means foo.jar is not running.
Try running ps aux | grep foo.jar | grep -v grep and see if you're actually seeing results.
As much as you may enjoy a half dozen pipes in your commands, you may want to look at the pkill command!
DESCRIPTION
The pkill command searches the process table on the running system and signals all processes that match the criteria
given on the command line.
i.e.
pkill foo.jar
Untested and a guess at best (be careful)
kill -9 $(ps -aux | grep foo.jar | grep -v grep | awk '{print $2}')
I re-iterate UNTESTED as I'm not at work and have no access to putty or Unix.
My theory is to send the kill -9 command and get the process id from a sub shell command call.

linux program does not start after sh gets killed

I need to start a program, which uses a serial port from within a bash script. The matter is that prior to doing that I need to kill "-sh" process in order to release the serial port occupied by it (I use a serial console and this is the only way to communicate with Linux). When I kill "-sh" my program doesn't start, however the bash script continues to execute. If I don't kill "-sh" my program normally starts. See code below for details:
#!/bin/bash
SH_PID=`ps -o comm,pid | egrep -e '^sh' | awk -F " " '{print $2}'`
kill -9 $SH_PID
myprog #start my program
while true
do
sleep 10
echo "script is running..." > /dev/ttyS0
done
Any thoughts?
What if you kill your shell after running your program in background:
#!/bin/bash
SH_PID=`ps -o comm,pid | egrep -e '^sh' | awk -F " " '{print $2}'`
nohup myprog & #start my program in background
kill --HUP $SH_PID
while true
do
sleep 10
echo "script is running..." > /dev/ttyS0
done

how to enable some commands during run time in a shell script

I have written 1 shell script to run Jstack command for a particular Process ID (PID).
But some time it may happen that multiple PIDs are there in a server for Java process.
At that case i want to run that many Jstack commands giving respective PIDs as input to the command.
Eg. If one application has 2 servers (1 tomcat and 1 jboss), then I need to run 2 JStack commands to capture 2 different logs for 2 processes.
So how to handle or check so that the script will automatically decide how many PIDs r there for java process and will run the commands written inside the script?
My script is getting all the PIDs active by
PID1=$(ps -ef|grep java|grep jboss| awk '{print $2}' )
and
PID2=$(ps -ef|grep java|grep tomcat| awk '{print $2}' )
after that I am running Jstack commands as
jstack $PID1 > jStack1.txt & and jstack $PID2 > jStack2.txt &
To get the pid you can just use pgrep instead of ps/grep/grep/awk:
for pid in $(pgrep -f "tomcat|jboss")
do
jstack $pid >> jStack1.txt
done
you need to combine the pids into one list and loop round them.
So something like this to get a seperate file for each pid:
for pid in $( ps -ef | egrep "tomcat|jboss" | awk '{print $2}')
do
jstack $pid > jstack.$pid.txt
done
Following on from your last comment
I'm not sure what you are trying to do with the array and multiple jstack calls in the loop as it will iterate once for each pid, not give you two pids in the loop, and the $0 & $1 indices don't make sense (did you mean just 0 & 1?), and you are using $N each time but the increment for it is commented out so will stay as 0.
If you are sure there can only be two pids, one for tomcat and one for jboss, then your inital code with sleeps added would do it:
#!/bin/bash
Sleep1=$1
# sleep for the first requested time
sleep $Sleep1
# do the tomcat jstack
PID1=$(ps -ef | grep java| grep tomcat | awk '{print $2}')
jstack $PID1 > jstack.tomcat.$PID1.txt
# sleep for another 60secs
sleep 60
# do the jboss jstack
PID2=$(ps -ef | grep java| egrep "jboss|JBoss" | awk '{print $2}')
jstack $PID2 > jstack.jboss.$PID1.txt
If there can be multiple tomcat processes and multiple jboss processes, then you need two loops:
#!/bin/bash
Sleep1 = $1
# sleep for the first requested time
sleep = $Sleep1
# Do all the tomcat jstacks
for pid in $(ps -ef | grep java| grep "tomcat" | awk '{print $2}')
do
jstack $pid > jstack.tomcat.${pid}.txt )
done
# sleep for another 60secs
sleep 60
# Do all the jboss jstacks
for pid in $(ps -ef | grep java| egrep "jboss|JBoss" | awk '{print $2}')
do
jstack $pid > jstack.jboss.${pid}.txt )
done
Or some combinations of these methods could be used depending on exactly what you are after.

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!

Bash script optimization for waiting for a particular string in log files

I am using a bash script that calls multiple processes which have to start up in a particular order, and certain actions have to be completed (they then print out certain messages to the logs) before the next one can be started. The bash script has the following code which works really well for most cases:
tail -Fn +1 "$log_file" | while read line; do
if echo "$line" | grep -qEi "$search_text"; then
echo "[INFO] $process_name process started up successfully"
pkill -9 -P $$ tail
return 0
elif echo "$line" | grep -qEi '^error\b'; then
echo "[INFO] ERROR or Exception is thrown listed below. $process_name process startup aborted"
echo " ($line) "
echo "[INFO] Please check $process_name process log file=$log_file for problems"
pkill -9 -P $$ tail
return 1
fi
done
However, when we set the processes to print logging in DEBUG mode, they print so much logging that this script cannot keep up, and it takes about 15 minutes after the process is complete for the bash script to catch up. Is there a way of optimizing this, like changing 'while read line' to 'while read 100 lines', or something like that?
How about not forking up to two grep processes per log line?
tail -Fn +1 "$log_file" | grep -Ei "$search_text|^error\b" | while read line; do
So one long running grep process shall do preprocessing if you will.
Edit: As noted in the comments, it is safer to add --line-buffered to the grep invocation.
Some tips relevant for this script:
Checking that the service is doing its job is a much better check for daemon startup than looking at the log output
You can use grep ... <<<"$line" to execute fewer echos.
You can use tail -f | grep -q ... to avoid the while loop by stopping as soon as there's a matching line.
If you can avoid -i on grep it might be significantly faster to process the input.
Thou shalt not kill -9.

Resources