6

ctrl-z (^z) acts in ways I do not understand when done inside a loop executed from a terminal.

Say I type

for ii in {0..100}; do echo $ii; sleep 1; done

then I hit ^z. I'll get:

[1]+  Stopped                 sleep 1

I can resume the job using fg or bg, but the job refers only to he sleep command. The rest of the loop has apparently disappeared, and no more number appear on the terminal.

I could use & after the command to immediately run it in the background, or another solution is to wrap the whole thing in a subshell:

( for ii in {0..100}; do echo $ii; sleep 1; done )

then ^z gives me

[1]+  Stopped                 ( for ii in {0..100};
do
    echo $ii; sleep 1;
done )

This job can be resumed and everyone is happy. But I'm not generally in the habit of doing this when running a one-off task, and the question I am asking is why the first behavior happens in the first place. Is there a way to suspend a command-line loop that isn't subshell'd? And what happened to the rest of the loop in the first example?

Note that this is specific to the loop:

echo 1; sleep 5; echo 2

and hitting ^z during the sleep causes the echo 2 to execute:

1
^Z
[2]+  Stopped                 sleep 5
2

Or should I just get in the habit of using & and call it dark magic?

4

1 回答 1

6

您不能暂停当前 shell的执行。当您从命令行运行循环时,它正在您当前的登录 shell/终端中执行。当您按下 [ctrl+z] 时,您是在告诉 shell 暂停当前的活动进程。您的循环只是当前 shell 中的一个计数器,正在执行的进程是sleep. 暂停只对睡眠起作用。

当您将一个进程作为背景或在子 shell 中执行它(大致等效)时,您可以完全暂停该单独的进程。

于 2014-11-14T21:47:21.050 回答