killing the background process in a shell script - shell

I have a script that starts background processes.
#!/bin/sh
./process1.sh &
./process2.sh &
I need to kill these processes using a separate script.
Here is what I did:
#!/bin/sh
# the kill.sh
pid=$(ps | grep './process1.sh' |grep -v grep| awk '{print $1}')
kill -9 $pid
Question time:
When the kill.sh is called processes are stoped. But I get the message
"sh: you need to specify whom to kill".
Why is that?
After I kill the process using the described script, it doesn't stop immediately.For a while I see the output on the screen as if the process is still running. Why?
What could be an alternative solution to kill the processes?
Worth to mention that I am working with busybox do I have limited choice of utilities.

You could store the process ids in a temporary file like this:
#!/bin/sh
./process1.sh &
echo $! > /tmp/process1.pid
./process2.sh &
echo $! > /tmp/process2.pid
and then delete it with your script. $! returns the PID of the process last executed.
kill -9 `cat /tmp/process*.pid`
rm /tmp/process*.pid
Make sure the process*.pid files get deleted after the corresponding script is finished.

Because your kill command failed as pid is empty.
pid=$(ps | grep './process1.sh' |grep -v grep| awk '{print $1}')
This doesn't give you the pid you want. When you start a process in the background, it's executed in a new shell and you won't see the process.sh in your ps output.
What you can do is save the PIDs when you start the background processes and kill them:
./process1.sh &
pid1=$! # Save the previously started background's PID
./process2.sh &
pid2=$! # Save the previously started background's PID
echo $pid1 " " $pid2 > /tmp/killfile
Then get the PIDs from this file and pass it to kill.

Related

How to kill a process group with kill in bash?

I have a script which is much more complicated but I managed to produce a short script that exhibits the same problem.
I create a process and make it a session leader and then send SIGINT to it. The kill builtin doesn't fail but the process doesn't get killed either (i.e. the default behaviour for SIGINT is to kill). I tried with kill -INT -pid (which should be equivalent to what I do currently) and the /bin/kill command but the behaviour is the same.
The script is as follows:
#!/bin/bash
# Run in a new session so that I don't have to kill the shell
setsid bash -c "sleep 50" &
procs=$(ps --ppid $$ -o pid,pgid,command | grep 'sleep' | head -1)
if [[ -z "$procs" ]]; then
echo "Couldn't find process group"
exit 1
fi
PID=$(echo $procs | cut -d ' ' -f 1)
pgid=$(echo $procs | cut -d ' ' -f 2)
if ! kill -n SIGINT $pgid; then
echo "kill failed"
fi
echo "done"
ps -P $pgid
My expectation is that the last ps command shouldn't report anything (as kill didn't report failure and hence the process should have died) but it does.
I am looking for an explanation of the above noted behaviour and how I can kill a process group (i.e. both the bash and the sleep it starts -- the setsid line above) running in a separate session.
I think you'll find that sleep ignores SIGINT. Take a look at the signals of your sleep command and see. On my Linux box I find:
SigIgn: 0000000000000006
The second bit from the right is set (6 = 4 + 2 + 0), and from the above link:
--> 2 = SIGINT
Try send a HUP, and you'll find it does kill the sleep.

find and kill process in ksh script (linux) not working

I have been trying to find and kill any stale process left after the stop in a ksh script on a linux machine and it doesnt seem to work. It works from the command line but in the script though
here is the code
echo "kill any process still running"
ps -ef | grep qpasa |grep -v grep | awk '{print $2}' |xargs kill
and here is the output from the script log
usage: kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
can you you please let me know what am I doing wrong here
I think you call the script when no processes are running. Try kill without arguments and you get the same message.
You can redirect the error to /dev/null but I would try something else:
ps -ef | grep qpasa |grep -v grep | awk '{print $2}' | while read pid; do
echo "Killing ${pid}"
kill ${pid}
sleep 2
kill -9 ${pid} 2>/dev/null
done
The first kill gives qpasa the possibility to the stop controlled: Flush caches and close handles. Give qpasa 2 seconds for it.
When qpasa ignores the signal, kill it the hard way. Of course the process could have stopped already, so this time we want to ignore error messages.
When you have a lot of qpasa processes, you want to sleep 2 seconds only once.
First loop through all processes with a friendly kill, wait 5 seconds, and than hard kill the processes you find. When you make a function kill_qpasa_signal for the looping (and using $1 as kill signal), you can use
kill_qpasa_signal 15
sleep 5
kill_qpasa_signal 9

Kill running background jobs inside a shell script

I have created a shell script that runs multiple processes in the background, and at the end listens for the user's keyboard, when enter is pressed, it kills the previously created processes.
Something like :
#!/bin/sh
process_1 &
process_2 &
process_3 &
read -p "PRESS [ENTER] TO TERMINATE PROCESSES." PRESSKEY
kill -2 `jobs -p`
Notice that I run the processes in the background (the later &), I thought that when I do something like :
kill -2 `jobs -p`
All the jobs running in the background would be killed, but it actually tells me that my command is invalid, so I assume that jobs -p doesn't return anything.
Any idea on how to kill process_1 process_2 and process_3 ?? Thanks in advance.
You can store the PIDs in a space separated list and kill that:
process_1 & pids="${pids-} $!"
process_2 & pids="${pids-} $!"
process_3 & pids="${pids-} $!"
read -p "PRESS [ENTER] TO TERMINATE PROCESSES." PRESSKEY
kill -2 $pids # Without quotes to make the PIDs separate arguments
(The ${pids-} syntax is to avoid errors when using set -o nounset.)
Try this:
kill $(ps|grep 'process_1'|awk '{print $1}')
Explanation:
ps returns a list of running process. We grep for only the one we want to kill and the use awk to get only the PID of the process.

run command in bash and then exit without killing the command

I am attempting to run a couple commands in a bash script however it will hang up on my command waiting for it to complete (which it wont). this script is simply making sure its running.
#!/bin/bash
ps cax | grep python > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running... Starting..."
python likebot.py
echo $(ps aux | grep python | grep -v color | awk {'print $2'})
fi
Once it gets to the python command it hangs up while the command is being executed. its not till i cntrl c before it gives the pid. is there anyway i can have it run this bash script and exit the bash script once the commands were run (without waiting for them to complete).
In general, if you want to execute a command and not wait for it, you can simply use & as the delimiter rather than ; or a newline. When doing so, the pid of that process is available to the shell in the special variable !. If you want to wait for that process to complete, you can use wait. If you do not wish to wait for it, then simply omit the wait. In your case:
python likebot.py & # Start command asynchronously
echo $! # echo the pid of the most recent asynchronous process
Since it looks like likebot should be always running you might want to consider 'nohup' as well, with a bare & the job is still a child of your login process and will die if that dies.

Bash: wait for process to exit while tailing log file

In a bash script, I'm waiting on a child process's pid using wait. That child process is writing to a log file. Is there a way in the bash script to tail that log file to std out while at the same time waiting on the process to complete?
Use the tail command to follow the file while you wait for the command to finish.
command &
cmdpid=$!
tail -f -n +0 logfile &
wait $cmdpid
kill $!
This is in spirit similar to William's solution, but with one important difference: it will correctly print the log file if it takes longer for command to finish than it does for cat to print the file (quite likely, as cat is very fast). The -n +0 option tells tail to print the whole file before it starts following updates.
Run cat in the background:
cmd-that-logs-to-file &
pid=$!
cat file &
wait $pid
kill $! # Kill the cat
This makes it simpler:
command &
pid=$!
tail --pid=$pid -f /path/to/log

Resources