perl – $SIG {INT} =’IGNORE’不使用Net :: OpenSSH
我需要在后台通过$ssh->系统执行命令,并且记录下这应该像本地“system”命令一样:
'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”版本是否可以中断? 此致 Mazze 解决方法
问题是当您在控制台上按CTRL-C时,内核会向进程组上的所有进程发送信号(请参阅
Prevent control-c from sending SIGINT to all process group children).
我认为你在行为中看到的差异实际上是由子进程的差异造成的,有些是重置信号标志,而有些则没有. 无论如何,我将添加对在不同进程组中运行SSH进程的支持.在模块RT上添加错误报告,所以我不要忘记它. 更新:以下实验表明OpenSSH系统方法和内置程序的行为方式相同: my @cmd = $SSH->make_remote_command("sleep 3 && echo hello"); warn "running command @cmdn"; 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进程. 请报告您可能发现的任何问题! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |