来自上一个问题看来我无法理解如何正确&&
交互^Z
:
$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+ Stopped
$ fg && command4
Running command3
Running command4
,我认为可以用来在链启动后“追加”链,似乎只因为是command3
最后一个命令才起作用;并停止它command2
,例如, who 会提供不同的结果(command3
who 应该被忽略)。
如何&&
在不取消其余命令的情况下优雅地挂起链?如果命令行中需要进一步的逻辑,我还希望保留退出代码。
如果我知道我可能想提前暂停链,我可以这样启动它:( command1 && command2 && command3 )
,所以它应该可以优雅地暂停。但是当它直接启动时我该怎么做?
如果命令不提供输出(与上面的示例不同),不应运行两次或乱序,那么我能想到的唯一方法是按^Z
,分析停止的内容,然后手动构建fd && the_rest_of_commands
,这是不方便且错误的 -易于。
答案1
我认为你误解了正在发生的事情。当你这样做时:
cmd1 && cmd2
shellcmd1
在子进程中启动,等待该进程,然后在以零退出状态退出cmd2
时启动。cmd1
如果按Ctrl+Z,等待返回,shell 设置$?
为 148 例如 (128 + SIGTSTP),其余部分的评估完成在那时候,也是cmd2
如此不是被执行。并cmd1
成为后台工作。
如果您输入:
cmd1 || cmd2
或者:
cmd1; cmd2
cmd2
会被处决之上Ctrl-Z并且您必须等待它完成才能收到下一个提示(如果可以fg
或bg
您的后台作业)。
在 中zsh
,当您按Ctrl-Zin 时:
{cmd1 && cmd2 && cmd3}
这会暂停整个组(并将其移至子 shell)。但是,在恢复时,挂起的命令在终止时将设置$?
为 20,无论其退出状态如何,我认为没有办法解决这个问题,因此您最终会得到相同的行为(尽管在{cmd1 || cmd2}
cmd2 中将在 cmd1 之后执行)已经完成而不是直接上Ctrl-Z)。
答案2
gdb -p
看起来像是通过提供优雅的暂停来暂停当前正在运行的组件,这与kill -STOP
.
因此,如果您知道command2
当前正在执行,您可以执行以下操作:
gdb -p $(pgrep -f 'command2')
从其他终端暂停,然后退出或继续 GDB 恢复。
答案3
您可以挂起父 shell - 您在其中启动命令的交互式 shell:
在运行命令之前打印 PID(或稍后查找 PID,见下文):
$ echo $$
1234
从另一个终端,您可以通过挂起交互式 shell 来停止整个命令列表 - 该列表由交互式 shell 的子进程组成:
$ kill -STOP 1234
并继续命令列表:
$ kill -CONT 1234
由于echo $$
在运行命令列表之前不需要进行任何准备(如 ),这是用例的一个重要部分,因此当列表已在前台运行时,以下是如何获取要停止的 shell 的 PID。
这个想法是找到列表中任何命令的父进程的 PID:
首先,我们用来pgrep
查找当前正在运行的命令的PID。找到其中任何一个的 PID 就足够了,因为一次只运行一个:
$ pgrep 'command1|command2|command3'
如果command1
等实际上不是进程的命令名称 - 即命令行的第一个单词 - 您需要添加该-f
选项(并用于-a
实验以查看不仅仅是PID):
$ pgrep -f 'command1|command2|command3'
然后,我们使用ps
查找命令的父PID:
$ ps -o ppid=
结合起来,我们得到要挂起的 shell 的 PID,如下所示:
$ pid=$(ps -o ppid= $(pgrep 'command1|command2|command3'))
全部一起:
$ kill -STOP $(ps -o ppid= $(pgrep 'command1|command2|command3'))
$ kill -CONT $(ps -o ppid= $(pgrep 'command1|command2|command3'))