33

I have written a bash script that calls several other programs and executes a bunch of commands. I run this script from the terminal. Now I want to kill the script.

Pressing Ctrl + C sometimes doesn't cut it, I think because sometimes the script is executing another program, and for some reason the kill signal doesn't work.

However, if I close the terminal window, it kills the script.

Is there something I can do (a keyboard combination), that is analogous to closing the terminal window, without actually closing the terminal window (I don't want to lose command history, current directory, output history, etc.)?

  • 8
    In such cases I try Ctrl + z – kenn Sep 4 '14 at 16:07
  • And after Ctrl + z run: kill -9 $(pgrep -f your_script.sh) – Noam Manos Feb 15 '18 at 8:22
35

You have few options. One is to stop the script (CtrlZ), get the PID of the script and send SIGKILL to the process group.

When a command is executed in a shell, the process it starts and all its children are part of the same process group (in this case, the foreground process group). To send a signal to all processes in this group, you send it to the process leader. For the kill command, process leader is denoted thus:

kill -PID

Where PID is the process ID of the script.

Example:

Consider a script test.sh which launches some processes. Say you ran it in a shell:

$ ./test.sh

In another terminal,

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

In this case, to send a signal to process group created by test.sh, you'd do:

kill -INT -17802

-INT is used to send SIGINT, and so this command is the equivalent of pressing CtrlC on the terminal. To send SIGKILL:

kill -KILL -17802

You only need to stop the script if you can't open another terminal. If you can, use pgrep to find the PID.

One of the commands that the script launches may be trapping SIGINT, which is probably why CtrlC is ineffective. However, SIGKILL can't be trapped, and it is usually a last-resort option. You might want to try SIGTERM (-TERM) before going for the kill. Neither SIGKILL or SIGTERM can be set up as a keyboard shortcut the way SIGINT is.

All this is moot if your script doesn't contain a shebang line. From this SO answer:

Usually the parent shell guesses that the script is written for the the same shell (minimal Bourne-like shells run the script with /bin/sh, bash runs it as a bash subprocess) ...

Because of this, when the script is executed, you won't find a process named after script (or a process with the script's name in the command line) and pgrep will fail.

Always use a shebang line.

  • Is there a keyboard combination for SIGKILL or SIGTERM? – becko Sep 4 '14 at 20:02
  • @becko No, and you can't set up one: superuser.com/a/417991/334516 – muru Sep 4 '14 at 20:07
  • pgrep test.sh doesn't return the PID for me. I tried a simple test.sh: for i in {1..30}; do sleep 1 echo $i done While test.sh is running, I execute pgrep test.sh in another terminal, but nothing is returned. What's wrong? – becko Sep 4 '14 at 20:21
  • 1
    @becko how did you run the script? Also try pgrep -f test.sh. – muru Sep 4 '14 at 20:22
  • pgrep -f test.sh doesn't work either. I run the script with ./test.sh – becko Sep 4 '14 at 20:23
5

If you know the processes that are associated with the script you can find their PID using

 ps -A

and then use the PID number to kill the corresponding processes using

 kill -9 PID_Number
  • 1
    That's too complicated. The script spawns several other programs, and these programs also spawn parallel processes. It is very hard to keep track of all these processes. There must be a simpler solution, something analogous to what happens when you close the terminal window. – becko Sep 4 '14 at 15:57
  • Can you try pkill -P $$ – Harris Sep 4 '14 at 16:26
0

As Harris said you could run Kill -9 PID_Number but you could also install the package known as htop to have an interactive process browser that makes finding specific processes a lot easier. htop also supports killing processes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.