包含 while 循环的 PuTTY 远程命令

包含 while 循环的 PuTTY 远程命令

我正在尝试自动执行通过 SSH 连接到远程服务器的几个常见任务。为此,我在几个已保存的会话中使用 PuTTY 及其“远程命令”选项(连接 > SSH)。我的远程命令如下所示:

~/scripts/test; $SHELL -l

执行的脚本因保存的会话而异,并执行不同的任务。$SHELL -l脚本执行完成后,保持 PuTTY 会话处于活动状态。

所有这些对于我运行的大多数脚本来说都运行良好。但是,我有一个使用 while 循环执行一系列命令,直到使用 Ctrl+C 终止。脚本启动正常,但终止后 PuTTY shell 不会保持活动状态。$SHELL -l似乎没有被执行。

具有此行为的示例脚本如下:

while true; do
echo "."
sleep 2
done

以下手动执行工作正常,我看到了第二条命令的预期输出:

~/scripts/test; echo "done"

但是,PuTTY“远程命令”的第二个命令没有执行。事实上,如果我将远程命令更改为包含echo,它就不会显示。

~/scripts/test; echo "done"; $SHELL -l

所以我想我的问题是:为什么列表中的第二个命令没有被远程命令执行,而手动运行时却可以执行?而且,更重要的是,我该怎么办?

如果相关的话,我在 Ubuntu 14.04 上运行 PuTTY。

答案1

当您运行puttyssh——我认为在这种情况下没有任何区别——使用在远程系统上运行的命令时,远程 ssh 服务器会将该命令作为 shell 命令运行:

/bin/bash -c '~/scripts/test; $SHELL -l'

因此,您bash在远程系统上有一个实例正在执行此管道。您还有另一个bash实例,由第一个实例启动,执行此“测试”脚本。

当您键入 Control-C 时,putty会将字符发送到远程系统,您的 TTY 会将其解释为中断字符。这会导致向连接到 TTY 的进程发送 SIGINT(中断信号)。这会中断这两个 shell 进程,导致它们都退出。您希望父 shell 实例忽略 SIGINT。

忽略 SIGINT 的 bash 命令是:

trap "" INT

因此,要禁用管道的 SIGINT,您需要将原始命令更改为:

trap '' INT; ~/scripts/test; $SHELL -l

但是这也会禁用子进程的 SIGINT,这会使“测试”脚本不受 Ctrl-C 的影响。因此,您需要为测试脚本重新启用 SIGINT。命令如下:

trap INT

您可以将该行添加到测试脚本本身,也可以将其添加到管道:

trap '' INT; ( trap INT; ~/scripts/test ); $SHELL -l

现在,当您按下 Ctrl-C 时,您应该中断“测试”进程,但不会中断正在执行命令管道的父进程。

您可以不使用 putty 或 ssh 来测试这一点。只需运行这些命令,并在“sleep”执行时尝试按 Ctrl-C:

bash -c 'sleep 15; echo foo'                  # Ctrl-C kills sleep; doesn't print "foo"
bash -c 'trap "" INT ; sleep 15; echo foo'    # Ctrl-C has no effect
bash -c 'trap "" INT; ( trap INT; sleep 15 ); echo foo'    # Kills sleep, prints "foo"

答案2

ctrl+c 执行 putty 远程命令实际上会中断 ssh 会话,因此应该预料到它不会执行剩余的远程命令。如果您的目的只是让会话继续保持活动状态,那么无限循环就足够了。

相关内容