Linux Shell Kill Signal Sigkill && Kill

Why I am not getting signal SIGKILL on kill -9 command in bash?

You cannot do that. Yes 9 is SIGKILL and Unix system by design doesn't allow any script/program to trap SIGKILL due to security reasons. Otherwise any script can trap & ignore SIGKILL which will make impossible to terminate that script by OS.

How do I stop a signal from killing my Bash script?

I believe you're looking for SIGTERM:

Example:

#! /bin/bash

trap -- '' SIGINT SIGTERM
while true; do
date +%F_%T
sleep 1
done

Running this example cTRL+C won't kill it nor kill <pid> you can however kill it with kill -9 <pid>.

If you don't want CTRL+Z to interrupt use: trap -- '' SIGINT SIGTERM SIGTSTP

What is the difference between kill and kill -9?

kill aka kill -TERM aka kill -15 is the safe and correct way of terminating a process. It's equivalent to safely shutting down a computer.

kill -9 is the unsafe way of brutally murdering a process. It's equivalent to pulling the power cord, and may cause data corruption.

See the Linux&Unix stack exchange for more information.

kill process using sigterm and escalate to sigkill after timeout

There's the timeout command, which allows you to cap a process' execution time and escalate to a SIGKILL if it doesn't respond promptly to the initial signal (SIGTERM by default). This isn't quite what you're asking for, but it might be sufficient.

To do what you're actually describing (send a signal, briefly await, then send a kill) you may have to do a bit of bookkeeping yourself, as this question details.

One option would be to use Upstart (or I imagine other service managers), which provides a kill timeout n command that does what you want.


As an aside, many systems would treat 30 minutes as much too long to wait for SIGTERM. Linux does something akin to what you're describing on shutdown, for instance, but gives processes barely a few seconds to clean up and exit before SIGKILLing them. For other use cases you certainly can have a long-lived termination like you describe (e.g. with Upstart), but YMMV.

Why is the KILL signal handler not executing when my child process dies

I couldn't find anything in the bash documentation that would explain the observed behavior, so I turned to the source code. Debugging lead to the function notify_of_job_status(). The line that prints the message about a killed subprocess can be reached only if all of the following conditions hold:

  1. the subprocess is registered in the job table (i.e. has not been disown-ed)
  2. the shell was NOT started in interactive mode
  3. the signal that terminated the child process is NOT trapped in the parent shell (see the signal_is_trapped (termsig) == 0 check)

Demonstration:

$ cat test.sh 
echo Starting a subprocess
LC_ALL=C sleep 100 &
Active_pid=$!
case "$1" in
disown) disown ;;
trapsigkill) trap "echo Signal SIGKILL caught" 9 ;;
esac
sleep 1
kill -9 $Active_pid
sleep 1
echo End of script

$ # Demonstrate the undesired message
$ bash test.sh
Starting a subprocess
test.sh: line 14: 15269 Killed LC_ALL=C sleep 100
End of script

$ # Suppress the undesired message by disowning the child process
$ bash test.sh disown
Starting a subprocess
End of script

$ # Suppress the undesired message by trapping SIGKILL in the parent shell
$ bash test.sh trapsigkill
Starting a subprocess
End of script

$ # Suppress the undesired message by using an interactive shell
$ bash -i test.sh
Starting a subprocess
End of script

How this removes the trace of the first test without executing echo Signal SIGKILL ?

The trap is not executed since the KILL signal is received by the sub-process rather than the shell process for which the trap has been set. The effect of the trap on the diagnostics is in the (somewhat arguable) logic in the notify_of_job_status() function.



Related Topics



Leave a reply



Submit