When I run a command (make on a large project) from the shell, I can type CtrlZ 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 CtrlZ never had this problem, but I don't know how to do that in a script.

What makes CtrlZ 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, 2013 at 22:03

4 Answers 4


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 from 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.

  • With which can be blocked do you mean ignored or handled? May 13, 2022 at 14:12
  • 1
    Of those two I would probably settle for handled, for ignoring something is a particular way of handling it.
    – peterph
    May 15, 2022 at 19:57

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, 2013 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, 2013 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, 2013 at 19:20

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.


Ctrl+C is used to kill a process with signal SIGINT, by other words it is a polite kill.

Ctrl+Z is used to suspend a process by sending it the signal SIGSTP, which is like a sleep signal, that can be undone and the process can be resumed again.

However when a process is suspended, we can resume it again by fg (resume in foreground) and bg (resume in background), but I can't resume a killed process, that is a difference between using Ctrl+C & Ctrl+Z.

How to view suspended process ?

When you have multiple suspended commands, to have them listed, you use the jobs command, and output will be :

[1]-  Stopped                 cat
[2]+  Stopped                 vi

How to kill a suspended process in background?

By using kill command :

kill %n where n is the job number (the one in square brackets from the jobs output), so I want to kill cat : kill %1.

You must log in to answer this question.

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