Bash – Interrupting a for-loop in bash, but only after an iteration is completed

bashforshellshell-script

Is there a way to interrupt/stop a for-loop in bash, but only after the current iteration is completed – ie. "between" done and do?

I'm running a for-loop on several directories, with a command that could be destructive unless it's allowed to complete – so I'd like to stop it when the command is finished with one directory, but before it starts on the next.

(Yes, I know I could've added a sleep or a read command before done – but I didn't, and the loop is already running…)

Best Answer

For already running: assuming the command is a program and thus runs as a child process under the shell running the script (or part thereof), and the script didn't give it a heredoc or herestring for input or it has read or at least buffered that input, you can stop after the process finishes by:

  • kill -STOP the shell (so it won't do anything after the current command)
  • wait until the child process finishes and goes zombie
  • kill -KILL the shell

(All as the same user or root, from another shell, of course.) If the body of the do ... done does two or more things on each iteration, this only catches it after a program that takes long enough real time you can get the -STOP in, which may or may not be the last program in the iteration.

In some (many?) cases it will work to simply kill -KILL the shell up front, which prevents the shell cleaning up its children as normally does, and let the child run and finally get reaped by init (or equivalent on your system). However, this might result in the child seeing some I/O errors or environment differences or errors or variations with any grandchildren it has, and this might still trigger the 'destructive' results you are trying to avoid.

Related Question