gpt4 book ai didi

perl - $SIG{INT} ='IGNORE' 无法与 Net::OpenSSH 一起使用

转载 作者:行者123 更新时间:2023-12-02 05:54:27 25 4
gpt4 key购买 nike

我需要通过 $ssh->system 在后台执行命令,并且有记录表明这应该像本地“系统”命令一样:

'As for "system" builtin, "SIGINT" and "SIGQUIT" signals are blocked.  (see "system" in perlfunc).'

实际上,这似乎不是真的,因为当收到 SIGINT 时,子级中的 $ssh->system 会立即终止,即使我明确想先“忽略”它:

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);

当运行此代码并在第一个“sleep 3”开始后尝试中断时,“$SSH->system”调用将立即结束。

但是,如果您使用下面的本地“系统”语句,则可以正确捕获 SIGINT。

在 Net::OpenSSH 的源代码中,我发现 $SIG{INT} 也在“system”子目录中显式设置为“IGNORE”。我不知道为什么这不起作用。

我们对任何可能的解决方案表示感谢,即使这意味着以不同的方式做事。最后,我只想远程执行命令并仍然保护它们免受 CTRL-C 的影响。

谢谢,

迷宫

更新:

感谢您的意见@salva。我进一步剥离了东西,最后它似乎是 ssh 的“-S”标志:

$SIG{INT}='IGNORE';
# system('ssh -S /tmp/mysock lnx0001a -- sleep 3');
system('ssh lnx0001a -- sleep 3');

一旦使用“-S/tmp/mysock”变体,ssh 似乎就可以中断,否则就不会。有谁可以对此做出解释吗?我应该为此发布一个新的独立问题吗?

再次感谢,

迷宫

更新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 创建主 session )。

真诚的,

迷宫

最佳答案

问题是,当您在控制台上按 CTRL-C 时,内核会向进程组上的所有进程发送信号(请参阅 Prevent control-c from sending SIGINT to all process group children )。

我认为您在行为中看到的差异实际上是由子进程的差异引起的,一些子进程重置了信号标志,而另一些则没有。

无论如何,我将添加对在不同进程组中运行 SSH 进程的支持。添加模块的错误报告RT所以我不要忘记它,拜托。

更新:以下实验显示 OpenSSH system 方法和内置方法的行为方式相同:

my @cmd = $SSH->make_remote_command("sleep 3 && echo hello");
warn "running command @cmd\n";
local $SIG{INT} = 'IGNORE';
system @cmd;

如果您运行它,您将看到信号到达并中止 ssh 进程,即使 INT 信号处理程序设置为 IGNORE 也是如此。

更新2:经过一些实验,我发现问题实际上出在后台运行的主SSH进程上。除非您使用密码身份验证,否则它也会卡在进程组中并因此获取 INT 信号。

我添加了一个新选项来明确要求将主进程作为新进程组运行,但是由于选项数量众多,这部分代码非常复杂,因此这不是一件容易的任务。

更新 3:我发布了新的 development version (0.61_15)模块的。

现在,你可以做...

my $ssh = Net::OpenSSH->new($host, master_setpgrp => 1, ...);
$ssh->system({setpgrp => 1}, "sleep 10; echo uninterruptible");

...希望主或从 SSH 进程不会收到任何 SIGINT。

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

关于perl - $SIG{INT} ='IGNORE' 无法与 Net::OpenSSH 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22790431/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com