bash:向while循环发送控制信号?

bash:向while循环发送控制信号?,bash,Bash,简单bash行: for h in $(cat /tmp/hosts); do ssh $h; done 如果我键入Ctrl-C,它将按预期退出for循环。但是我想要一种发送信号的方法,该信号将仅从当前ssh线路中断,并继续循环中的下一个迭代。如果我不想或无法登录到某个特定主机,但希望立即处理文件中的其他主机,那么这将非常有用。有没有一种方法可以指定一个可以以这种方式捕获的控制字符 答复: 我想出来了 for h in $(cat /tmp/hosts); do trap 'continue'

简单bash行:

for h in $(cat /tmp/hosts); do ssh $h; done
如果我键入Ctrl-C,它将按预期退出
for
循环。但是我想要一种发送信号的方法,该信号将仅从当前ssh线路中断,并继续循环中的下一个迭代。如果我不想或无法登录到某个特定主机,但希望立即处理文件中的其他主机,那么这将非常有用。有没有一种方法可以指定一个可以以这种方式捕获的控制字符

答复: 我想出来了

for h in $(cat /tmp/hosts); do trap 'continue' 3; ssh $h; done

信号3对应于
Ctrl-\
。因此,要终止当前ssh命令(在您登录主机之前,如果您已经登录,它将无法工作)并移动到循环中的下一个命令,请键入
Ctrl-\
。要终止整个“脚本”,请键入
Ctrl-C
。有效的;清洁的正是我所需要的。

当按ctrl+c时,默认情况下您所要求的应该发生。但是我发现你的命令有一些错误

首先,
while
循环和
ssh
命令都是从同一管道读取的。这可能会导致意外的结果,因为第一个
ssh
命令读取所有主机名,而
while
命令将在本应找到更多主机名时看到
EOF

该问题的通常解决方案是对
ssh
命令使用
-n
标志

此外,不建议在没有命令的情况下运行
ssh
,而
stdin
不是tty。我想您确实想在
ssh
命令中为远程系统添加一个命令

这是命令的外观:


读取h时
;执行ssh-n“$h”'睡眠10';完成我知道这不是您正在寻找的策略,但有一些替代方案不涉及从交互式shell窃取信号:

  • ssh
    有一个用于此目的的“终止”转义序列。按enter键后立即键入以下键(但仅限于准备丢失的会话):
    ~。
    请记住,这会杀死嵌套的
    ssh
    命令的最顶端;如果您的初始连接不是通过
    ssh
    命令进行的,则这对远程主机更有效。(正如你的评论和否决票所表明的,你正在筑巢)
  • Ctrl-D
    在一个空提示符上是一个优雅的shell挂起。为您省去了键入
    退出
    注销
    的麻烦,并建议您在后台运行程序。如果您真的需要突破
    ssh
    ,请坚持使用
    ~。

我同意卡斯佩德的观点,这不是一个好的设计方向。这是按计划进行的;您的
ctrl-c
被发送到远程shell,因为您正在以交互方式运行
ssh
。通过使用陷阱“修复”此问题,您已经消除了向远程shell发送中断信号的能力。这不仅会产生意料之外的后果,而且还违反了的设计原则。如果您的团队中有其他成员可能使用此脚本,请不要使用此方法。s/interrupt/quit/在我的评论中,但意见保持不变。在这个行业中,从交互式外壳窃取信号是件坏事。这种策略在业余爱好者的环境中是可以接受的,但我们这里有不同的受众。没有理由在循环的每次迭代中重新执行
trap
。在读取时使用
while-r varname
而不是
for
来迭代文件的内容。养成在变量展开时总是引用变量的习惯。在
/tmp/hosts
中添加一个额外的字段,0=notSeen,1=current,2=done。您的脚本搜索状态为“当前”的主机,请求重试,然后继续使用未看到的主机。当您中断ssh时,您可以重新启动脚本,该脚本将自动接收下一个主机。注释上下文:这篇文章最初是在ServerFault上发表的。我测试了上面键入的命令,按ctrl-c只会终止当前的
ssh
命令。但只有在
sleep
命令运行时按ctrl-c键,它才起作用。我可以在
ssh
登录时点击一个点,按下ctrl-c停止整个序列。此外,如果输入文件太长,以至于在完成之前可能会终止
cat
命令,则可能存在问题。我将更改命令以解决此问题。否。{Ctrl-c}只是杀死了整个循环。{~.}杀死了我的tmux会话。@Michael,因为你嵌套了多个ssh命令,但没有透露。没有嵌套任何东西。每个ssh都是独立执行的。您不明白的是什么?
~。
(无元字符)将终止以交互方式读取字符的
ssh
命令的第一次调用。就这样。如果某个东西意外死亡,则它位于
ssh
命令的另一端,或者该序列未在我描述的上下文中使用。它将终止我的tmux会话和调用它的shell。它不会影响for循环或ssh提示符。