bash:向while循环发送控制信号?
简单bash行: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'
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提示符。