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.
Related
I have a task(appium server) running in the background. I started this task by running the command appium & . After running my tests, i need to kill appium. I tried running kill <pid_of_appium> , but the task is not killed immediately. I manually have to press the Enter Key to kill it.
I initially thought this was a problem with appium alone, but I tried running several background tasks and all of these tasks are getting killed only after pressing the Enter key. How can i handle this through code as I need to stop the background task programmatically using a shell command
Be careful using kill -9. It can cause corrupted data and potential problems associated with that. I found this script that should attempt to kill the process with a signal -15, and then with a signal -9 as a last resort.
#!/bin/bash
# Getting the PID of the process
PID=`pid_of_appium`
# Number of seconds to wait before using "kill -9"
WAIT_SECONDS=10
# Counter to keep count of how many seconds have passed
count=0
while kill $PID > /dev/null
do
# Wait for one second
sleep 1
# Increment the second counter
((count++))
# Has the process been killed? If so, exit the loop.
if ! ps -p $PID > /dev/null ; then
break
fi
# Have we exceeded $WAIT_SECONDS? If so, kill the process with "kill-9"
# and exit the loop
if [ $count -gt $WAIT_SECONDS ]; then
kill -9 $PID
break
fi
done
echo "Process has been killed after $count seconds."
If a task doesn't respond to a general kill command, you can try kill -9 instead. Adding the -9 causes the kill program to dispatch a much more ruthless assassin to carry out the deed than the normal version does.
Give a try to pkill and pgrep:
pgrep, pkill -- find or signal processes by name
To find the process and print the PID you can use:
pgrep -l appium
To kill all the processes you can do:
pkill appium
In case want to send a a KILL 9 signal you could do this;
pkill 9 appium
A bash script demo.sh
#!/bin/bash
./prog1 &
./prog2 &
wait
Use timeout -s 9 5m demo.sh to run the script.
The script demo.sh used to be without & and wait. I want to know whether timeout will kill prog1 and prog2 when timeout happens. How can I make sure that all subprocesses would be killed?
The forked jobs will be killed when you kill the shell process started by
demo.sh (unless you do something like disown $PID).
You can ensure this happens with kill -0:
./prog1 &
echo P1=$!
./prog2 &
echo P2=$!
you can then kill -0 ${PID1} and kill -0 ${PID2} and ensure that both
commands return with exit status 1, which means "couldn't find process"
I have a small problem. In bash scripting i need to run an xterm who do some things like this.
xterm -e "(time ./program.exe 127.0.0.1) 2> out.txt"
How can i say the pid of this process?
I need to wait who it finisced for write the output and merge with another fine.
Thank so much to all!!
Basically you start the process in the background by adding & to the end of your command, get the last started pid with $! and wait on the process to complete with wait. So, something like:
xterm -e "(time ./program.exe 127.0.0.1) 2> out.txt" &
pid=$!
wait $pid
should work.
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.
I need to set a trap for a bash process I'm starting in the background. The background process may run very long and has its PID saved in a specific file.
Now I need to set a trap for that process, so if it terminates, the PID file will be deleted.
Is there a way I can do that?
EDIT #1
It looks like I was not precise enough with my description of the problem. I have full control over all the code, but the long running background process I have is this:
cat /dev/random >> myfile&
When I now add the trap at the beginning of the script this statement is in, $$ will be the PID of that bigger script not of this small background process I am starting here.
So how can I set traps for that background process specifically?
(./jobsworthy& echo $! > $pidfile; wait; rm -f $pidfile)&
disown
Add this to the beginning of your Bash script.
#!/bin/bash
trap 'rm "$pidfile"; exit' EXIT SIGQUIT SIGINT SIGSTOP SIGTERM ERR
pidfile=$(tempfile -p foo -s $$)
echo $$ > "$pidfile"
# from here, do your long running process
You can run your long running background process in an explicit subshell, as already shown by Petesh's answer, and set a trap inside this specific subshell to handle the exiting of your long running background process. The parent shell remains unaffected by this subshell trap.
(
trap '
trap - EXIT ERR
kill -0 ${!} 1>/dev/null 2>&1 && kill ${!}
rm -f pidfile.pid
exit
' EXIT QUIT INT STOP TERM ERR
# simulate background process
sleep 15 &
echo ${!} > pidfile.pid
wait
) &
disown
# remove background process by hand
# kill -TERM ${!}
You do not need trap to just run some command after a background process terminates, you can instead run through a shell command line and add the command following after the background process, separated with semicolon (and let this shell run in the background instead of the background process).
If you still would like to have some notification in your shell script send and trap SIGUSR2 for instance:
#!/bin/sh
BACKGROUND_PROCESS=xterm # for my testing, replace with what you have
sh -c "$BACKGROUND_PROCESS; rm -f the_pid_file; kill -USR2 $$" &
trap "echo $BACKGROUND_PROCESS ended" USR2
while sleep 1
do
echo -n .
done