9

I run my command in a loop. I wrote the loop directly to a bash command line:

$ while true; do mycommand; done

mycommand is a command doing a lot of io and waiting for events so it does not consume much processor time.

How can I interrupt the loop? When I press ctrl-c or ctrl-\ then mycommand is terminated but it is started again immediately. When I log in to another terminal and kill the command then the situation is the same.

Is it possible to interrupt the loop without killing the terminal session?

3 Answers3

13

A simple enough way to kill loops started interactively would be to stop the command (Ctrl-Z), which should print a job number, say [2]+ Stopped, which you can then kill using kill %2.

dhag
  • 15,736
  • 4
  • 55
  • 65
1

You want ps -f. pstree also is very useful. Have a look at the PPID (parent PID).

$ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
rui       7725  7722  0 13:30 pts/0    00:00:01 -bash
rui       8062  7725  0 14:09 pts/0    00:00:00 ps -f

$pstree -g

├─starter(1600)───charon(1603)─┬─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ ├─{charon}(1603) │ └─{charon}(1603)

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
1

A little background:

Your command mycommand doesn't resend SIGINT when it receives one, and just terminates instead. Because of this, bash instance running the loop cannot determine that CTRL+C was used to terminate execution, and assumes it was just a keyboard shortcut you issued for mycommand. Since it would be undesirable to terminate your shell because of a keyboard shortcut (imagine using vi for instance), bash just goes on and executes another loop iteration.

The ultimate solution would be to fix mycommand, so that it kills itself with SIGINT when it receives one, letting bash know it should stop as well.

void sigint_handler(int sig)
{
    // Execute your normal handler
    signal(SIGINT, SIG_DFL); // don't catch the signal anymore
    kill(getpid(), SIGINT); // kill itself with the same signal
}

Source: http://www.cons.org/cracauer/sigint.html

If you cannot fix mycommand, you'll have to either close the terminal session, or kill the bash process which does the looping and the current instance of mycommand, in that order.