Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

When I run a command (make on a large project) from the shell, I can type Ctrl-Z to stop the process and return to the shell. Subsequently, I can run fg to continue the process.

I'm trying to write a shell script to automate this (specifically, to check my CPU temperature every few seconds and stop the process if it gets too hot, since my computer is prone to overheating). My first attempt worked like this (simplified):

make &

sleep 2
# If the CPU temperature is too high...
kill -STOP "$subpid"

sleep 2
# If the CPU temperature has dropped to safe levels...
kill -CONT "$subpid"

wait "$subpid"

Unfortunately, this didn't work; sending SIGSTOP to the process didn't pause it (as made evident by its continuing to send output to the terminal). I ran make & at the command line, sent SIGSTOP, and checked the process status with ps; it was listed as stopped (and started again when I sent SIGCONT), but it was still spewing output and driving up my core temperature! Stopping it with Ctrl-Z never had this problem, but I don't know how to do that in a script.

What makes Ctrl-Z different from kill -STOP, and how can I get the behavior of the former in a shell script?

And yes, make is being run recursively. In fact, I think it goes several levels deep. –  Taymon Mar 20 '13 at 22:03

3 Answers 3

What makes Ctrl-Z different from kill -STOP, and how can I get the behavior of the former in a shell script?

CTRL-Z usually sends SIGTSTP (which can be blocked), and apart form other things shells often reset tty to a previously saved state on these occasions. More importantly however, the controlling terminal process group is set to the shell's PID (and then again to a PID of a job resumed with fg).

Back to your original problem: using a temperature dependent frequency scaling like e.g. Cpufreqd might be actually a better hammer for your nail.


You don't want to stop the make process; you want to stop the make process and all of its child processes. I bet make was being run recursively.

You could try set -m, then use %1 instead of "$subpid".

The set -m enables "job control", which is off by default inside scripts. I think it should work for your use case, although people seem to think it's a bad idea in general.


You can send a signal to all processes in a process group if you specify negative PID value - PGID of a session leader.

kill -STOP -"$subpid"

Note: To run a program in a new session use setsid make. But in your case I think it is not needed. However, if make is run recursively, each instance of make could be its own leader (I'm not sure about that).

Another option could be to use killall:

killall -STOP make

The difference between Ctrl+Z and kill -STOP:

  • Ctrl-Z actually sends TSTP, which can be blocked.
  • STOP cannot be blocked.
The PGID approach didn't work, and produced the following line of output: /usr/local/bin/myscript: line 38: kill: (-10202) - No such process. The background processes continued to run. I don't think the killall approach would work because some of the subprocesses appear to be sh rather than make. –  Taymon Mar 20 '13 at 22:52
It seems that the process you are sending the signal to has already finished. Subprocesses named sh are spawned by make. In your case of make and many subprocesses the best would probably be to obtain PIDs of all the children and STOP them all. –  Jurij Mar 22 '13 at 15:50
It ended up working when I did it manually from the shell, but not in a shell script. I'm thinking this is because when I did it manually, the root PID (which the others inherited their PGID from) was that of the first make command, but when I did it from the script, the root PID was from the shell script itself. –  Taymon Mar 22 '13 at 19:20

This site is currently not accepting new answers.

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