2

The full title of this question is:

Bash: What to do when control-c won't kill a process, due to the fact that the bash script contains a loop which calls another process: Is there a better solution to the on/off power button?

The title of this question is fairly self explanatory, but here's some more detailed information:

I have a bash script running which calls another program. (Runs / executes another program.)

This program is a data/curve fitting program, which cannot be interrupted with CTRL-C. But, from reading this post, I found I can kill it with CTRL-\

Hypothetical Thoughts...

So it is possible to just mash the keyboard, holding CTRL down, and mashing the \ key, BUT what if you bought a really expensive mechanical keyboard yesterday and don't have enough money to buy another cheap keyboard you're willing to "mash" (because you don't want to use up any of those 10^6 key-presses you have before your shiny new mechanical keyboard will wear out), or alternatively don't have enough time to find your old keyboard in your house because your house is either extremely disordered (a mess) or because there is an emergency such as a chip-pan fire occurring simultaneously...

Also consider that a loop is calling this fitting program and perhaps you're fitting 1000 data files, pressing the \ key 1000 times is likely to take a long time.

Hyperspace Thoughts...

Or even; what if you made a mistake in the bash script and it's actually executing an infinite loop?

What can you do to stop the parent script running in this situation? You could unplug your computer, hold the power button down for 10 seconds to turn it off, or throw it into the chip-pan fire to stop it working, but these solutions seem insensible due to the possible loss of data which may occur.

In theory, one could run the system monitor and perhaps quit the bash process, but this may be difficult to find if you have many such processes all with the same name... In addition, you might have a single core computer, or a multicore computer with say N cores, running N processes which are all trying to use 100 % CPU. Or perhaps just 1 process is using more than the 4 GB of ram you have and so your computer is extremely slow for that reason... Too slow at least to run the system monitor for now. The next best option after this is to press CTRL-ALT-F1 and try to log in as root and find the offending bash parent using ps -A then kill PID... But again, this can take many minutes of your time if you computer is so heavily loaded that it is writing continually to swap.

SIG TERM exec cpu_broken.sh; reconvene; clear screen; clear thought_processes; continue...

Is there a better solution?

3 Answers 3

2

So basically you run a script that makes everything inaccessible, and you want quick and easy solution to stop it . An alternative to powercycling is to hold SYSRQ key (it's same as PRTSC key in many cases), and press one by one R, E, I,S,U,B. Basically that's a safe way to kill all running processes and restart the system.

Alternative to that is to do sudo nano /proc/sysrq-trigger, write b , in that file and save. The system will restart immediatelly

More info: https://en.wikipedia.org/wiki/Magic_SysRq_key

3
  • REISUB is forced reboot. Sometimes, keyboard becomes completely inaccessible and you cannot do REISUB either. Jun 16, 2015 at 17:37
  • In that case, I can only think of power-cycling the machine. I mean, there's no other way to interact with the system. Perhaps you could create a udev rule that detects a particular usb disk being connected and restarts the system, but if the system is hoaged , it probably won't run Jun 16, 2015 at 17:41
  • Yes. exactly like my case. I have USB keyboard and it becomes completely unresponsive where REISUB is required. Jun 16, 2015 at 17:42
1

You need to kill the whole process group. The process group ID (PGID) is the PID of the process that started the group. To kill the process group you need to find the PID of the process that started the process group i.e. the script or command that started it all. The syntax is:

kill -- -PGID

For example:

kill -- -1234

Here 1234 is the PGID (Process Group ID).

This will send SIGTERM to all processes in the process group. To send a different signal e.g. SIGKILL (9) do:

kill -9 -1234

How to find the PGID:

You can do:

ps -eo 'pid,ppid,pgid,cmd'

This will shoe the PID, PPID (parent process ID), PGID and the process name.

Now you can use grep or any other suitable method to find the PGID and then kill it by the methods mentioned above.

The reason i have make the command to show PPID is because you can also try to kill the process based on PPID matching by pkill:

pkill -P PPID

For example:

pkill -P 6789

Using this method you need to find all the parent (and child processes) and then kill them, so in my opinion killing the whole process tree is a better way if you want to kill all of them.

1

Usually you can use top, htop or similar to find the process and and kill it (or if you know the name or PID of the process, you can killall, pkill etc). For example, using top, I can select a script running from terminal and kill it by pressing k+Enter:

enter image description here

If that does not work, k+9+Enter should use the SIGKILL signal. SIGKILL requests that the process be killed immediately, and doesn't wait for the process to finish cleaning up resources etc like SIGTERM does. Ctrl+C a process only sends SIGINT to interrupt the process, like SIGTERM does.

Using the the tree view (press t) in htop also eans you can determine the parent processes of a script, and kill those to make sure it does not carry on looping.

See also:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .