'As for "system" builtin,"SIGINT" and "SIGQUIT" signals are blocked. (see "system" in perlfunc).'
实际上,这似乎并不正确,因为当接收到SIGINT时,子节点中的$ssh->系统会立即终止,即使我明确要先“忽略”它:
use warnings; use strict; use POSIX ":sys_wait_h"; use Net::OpenSSH; my $CTRLC=0; $SIG{CHLD}='IGNORE'; sub _int_handler { $CTRLC++; print "CTRL-C was pressed $CTRLC times!!!\n"; } $SIG{INT}='IGNORE'; my $SSH=Net::OpenSSH->new('testhost',forward_agent => 1,master_stderr_discard => 1,master_opts => [ -o =>"PasswordAuthentication=no"]); $SIG{INT}=\&_int_handler; sub _ssh { $SIG{INT}='IGNORE'; $SSH->system('sleep 3; sleep 3'); # system('sleep 3; sleep 3'); print "Exiting Child!\n"; exit 0; } print "Starting shell ...\n"; _ssh if not (my $PID=fork); print $PID,"\n"; waitpid ($PID,0);
当运行此代码并尝试在第一个“睡眠3”启动后立即中断时,“$SSH->系统”调用立即结束.
但是,如果您使用下面的本地“系统”语句,则会正确捕获SIGINT.
在我发现的Net :: OpenSSH的源代码中,$SIG {INT}也在“system”子系统中显式设置为“IGNORE”.我不知道为什么这不起作用.
我会感谢任何可能的解决方案,如果它意味着以不同的方式做事.最后,我只是想远程执行命令并仍然保护它们免受CTRL-C的攻击.
谢谢,
Mazze
更新:
感谢您输入@salva.我进一步剥离了东西,最后它似乎是ssh的“-S”标志:
$SIG{INT}='IGNORE'; # system('ssh -S /tmp/mysock lnx0001a -- sleep 3'); system('ssh lnx0001a -- sleep 3');
一旦使用“-S / tmp / mysock”变体,ssh似乎是可中断的,而不是其他.有没有人可以解释一下?
我应该发布一个新的独立问题吗?
再次感谢,
Mazze
更新2:
我把事情搞得更多,现在这完全没有任何perl范围.你可以在你的shell中做到这一点:
$trap '' INT $ssh lnx0001a -- sleep 3
现在不能打断.
但是,在我的情况下,以下内容仍然是可中断的:
$ssh -S /tmp/mysock lnx0001a -- sleep 3
使用CTRL-C,会立即中断.与root用户的情况与我的情况相同,但其他同事不会在其用户中看到此行为.我们比较了@ENV,但我们没有发现可能导致不同行为的原因.
你怎么样:在你的shell中“trap”’INT’后,“-S”版本是否可以中断?
(显然,您必须先为/ tmp / mysock创建一个主会话).
此致
Mazze
解决方法
我认为你在行为中看到的差异实际上是由子进程的差异造成的,有些是重置信号标志,而有些则没有.
无论如何,我将添加对在不同进程组中运行SSH进程的支持.在模块RT上添加错误报告,所以我不要忘记它.
更新:以下实验表明OpenSSH系统方法和内置程序的行为方式相同:
my @cmd = $SSH->make_remote_command("sleep 3 && echo hello"); warn "running command @cmd\n"; local $SIG{INT} = 'IGNORE'; system @cmd;
如果运行它,即使INT信号处理程序设置为IGNORE,您也会看到信号到达并中止ssh进程.
更新2:经过一些实验,我发现问题实际上存在于后台运行的主SSH进程上.除非您使用密码身份验证,否则它也会挂起进程组,因此会获取INT信号.
我正在添加一个新选项,明确要求将master作为一个新的进程组运行,但由于选项数量很多,代码的这一部分非常复杂,所以这不是一件容易的事.
更新3:我发布了一个新的development version (0.61_15)模块.
现在,你可以……
my $ssh = Net::OpenSSH->new($host,master_setpgrp => 1,...); $ssh->system({setpgrp => 1},"sleep 10; echo uninterruptible");
…并且希望没有SIGINT进入主进程或从进程SSH进程.
请报告您可能发现的任何问题!