加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – $SIG {INT} =’IGNORE’不使用Net :: OpenSSH

发布时间:2020-12-16 06:17:56 所属栏目:大数据 来源:网络整理
导读:我需要在后台通过$ssh-系统执行命令,并且记录下这应该像本地“system”命令一样: 'As for "system" builtin,"SIGINT" and "SIGQUIT" signals are blocked. (see "system" in perlfunc).' 实际上,这似乎并不正确,因为当接收到SIGINT时,子节点中的$ssh-系统会
我需要在后台通过$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”版本是否可以中断?
(显然,您必须先为/ tmp / mysock创建一个主会话).

此致

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进程.

请报告您可能发现的任何问题!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读