For example,
#!/bin/bash
while :
do
sl
done
How to terminate this bash script?
Ctrl-Z
to suspend the scriptkill %%
The %%
tells the bash built-in kill
that you want to send a signal (SIGTERM by default) to the most recently suspended background job in the current shell, not to a process-id.
You can also specify jobs by number or by name. e.g. when you suspend a job with ^Z, bash will tell you what its job number is with something like [n]+ Stopped
, where the n
inside the square brackets is the job number.
For more info on job control and on killing jobs, run help jobs
, help fg
, help bg
, and help kill
in bash, and search for JOB CONTROL
(all caps) or jobspec
in the bash man page.
e.g.
$ ./killme.sh ./killme.sh: line 4: sl: command not found ./killme.sh: line 4: sl: command not found ./killme.sh: line 4: sl: command not found ./killme.sh: line 4: sl: command not found ./killme.sh: line 4: sl: command not found ... ... ... ./killme.sh: line 4: sl: command not found ^Z [1]+ Stopped ./killme.sh $ kill %% $ [1]+ Terminated ./killme.sh
In this example, the job's number was 1, so kill %1
would have worked the same as kill %%
(NOTE: I don't have sl
installed so the output is just "command not found". in your case, you'll get whatever output sl produces. it's not important - the ^Z
suspend and kill %%
will work the same)
sl
) being run in the loop, but the script will keep running...and start another sl
. If you press ^C a few times really fast, you may get to kill both the sl
and the script (if neither of them trap SIGINT). ^Z will suspend the script almost immediately (immediately if you don't count buffered output that is still being printed to your terminal), so you can kill it with kill %%
sl
is a fun program". This time, it fun me again! @_@
Commented
Sep 18, 2012 at 3:07
%%
? I see no mention of it in the kill
manpage. Nor anything about background processes.
Commented
Feb 18, 2018 at 5:16
The symbols %% and %+ refer to the shell's notion of the current job, which is the last job stopped while it was in the foreground or started in the background. The previous job may be referenced using %-. If there is only a single job, %+ and %- can both be used to refer to that job
The program sl
purposely ignores SIGINT
, which is what gets sent when you press Ctrl+C. So, firstly, you'll need to tell sl
not to ignore SIGINT
by adding the -e
argument.
If you try this, you'll notice that you can stop each individual sl
, but they still repeat. You need to tell bash
to exit after SIGINT
as well. You can do this by putting a trap "exit" INT
before the loop.
#!/bin/bash
trap "exit" INT
while :
do
sl -e
done
If you want ctrl+c to stop the loop, but not terminate the script, you can place || break
after whatever command you're running. As long as the program you're running terminates on ctrl+c, this works great.
#!/bin/bash
while :
do
# ctrl+c terminates sl, but not the shell script
sl -e || break
done
If you're in nested loop, you can use "break 2" to get out of two levels, etc.
The easiest way is to issue the QUIT
signal, which is usually attached to Control-Backslash
.
When you see the train, hit Control-\
You can terminate that script by pressing Ctrl+C from terminal where you started this script. Of course this script must run in foreground so you are able to stop it by Ctrl+C.
Or you can find PID (Process ID) of that script in other opened terminal by:
ps -ef | grep <name_of_the_script>
kill -9 <pid_of_your_running_script>
Both ways should do the trick your are asking for.
Another way to terminate the entire script would be to background the sl
command and then trap signal INT
to kill the entire process group of the script with signal HUP
.
#!/bin/bash
trap 'trap - INT; kill -s HUP -- -$$' INT
#trap 'trap - INT; kill -s HUP 0' INT
while :
do
sl & wait
done
You can kill
the pid
of shell (bash).
I just tried and it works.
Because I cannot see the process from ps -ef
(the job that we run in the looping script).
Put at the end of script:
kill -9 $PPID
exit
use set -e
to exit from failure.
#!/bin/bash
set -e
while :
do
sl
done
while [ true ]
do
#check if script is running
ps | grep script_name.sh | grep -v grep >/dev/null 2>&1
if [ "$!" != "0" ] ; then
break
else
kill -9 ` ps -ef | grep script_name.sh | cut -d "a" -f 1`
echo "kill -9 `get script PID`"
fi
done
this should help.
The killing thing is awful, because you never now, if the script has to run twice. AND your exit code is wrong.
while [ something ]; do
if [ somethingelse ]; then
echo shut down script with exit code 0
exit 0
fi
done
echo something else not happend
exit 2 # Return val important for example for monitoring
No working. Solution = use perl. while opens own bash
ctrl-c
to send theSIGINT
signal (in most shells) or you can pressctrl-z
that sends theSIGTSTP
signal (in most shells). In the case you pressedctrl-z
the related process isn't killed but paused. You can resume it withfg
(at least inbash
)while
which keeps starting newer and newersl
instances will also receive aSIGINT
.sl
command which I believe is an annoing command for those who misspellls
, showing a train passing slowly by. As far as I know it traps theSIGINT
signal and must be killed withSIGKILL
.