perl fork不';远程运行时无法正常工作(通过ssh)

perl fork不';远程运行时无法正常工作(通过ssh),perl,unix,ssh,fork,Perl,Unix,Ssh,Fork,我有一个perl脚本,script.pl,它在运行时执行fork,父进程将其pid输出到一个文件,然后退出,而子进程输出要执行的内容,然后进入while循环 $pid = fork(); if ( ! defined $pid ) { die "Failed to fork."; } #Parent process elsif($pid) { if(!open (PID, ">>running_PIDs")) { warn "Error o

我有一个perl脚本,script.pl,它在运行时执行fork,父进程将其pid输出到一个文件,然后退出,而子进程输出要执行的内容,然后进入while循环

$pid = fork();

if ( ! defined $pid ) 
{
    die "Failed to fork.";
}
#Parent process
elsif($pid)
{
    if(!open (PID, ">>running_PIDs"))
    {
        warn "Error opening file to append PID";
    }
    print PID "$pid  \n";
    close PID;
}
#child process
else
{
    print "Output started";

    while($loopControl)     
    {
           #Do some stuff
    }
}
当我在本地调用它(即:perlscript.pl)时,它工作得很好

脚本打印出一些内容,然后将控制权返回shell。(当子进程在后台进入循环时)

但是,当我通过ssh调用时,控制永远不会返回到shell(也不会打印“Output start”行)

即: $sshusername@example.com“perl script.pl”

然而,有趣的是,子进程确实在运行(当我键入ps时可以看到它)

有人能解释发生了什么事吗

编辑:

我在debug下运行了它,得到了以下结果:

###分叉,但不知道如何创建新的TTY。 由于两个调试器争夺同一个TTY,因此输入严重纠缠

我知道如何在xterms中将输出切换到其他窗口 仅限OS/2控制台。对于手动开关,请输入创建的TTY的名称 在$DB::fork\u TTY中,或定义一个函数DB::get\u fork\u TTY()返回此值

在类UNIX系统上,可以获得给定窗口的TTY名称
通过键入tty,并通过sleep 1000000断开shell与tty的连接。

sshusername@example.com“nohup perl script.pl”


您无法退出,因为仍然连接了一个进程。您需要
nohup
它。

发生的情况是ssh正在直接以命令的形式执行“perl script.pl”。如果您有可用的“screen”,您可以执行以下操作:

$ ssh username@example.com 'screen -d -m perl script.pl'

要使其在分离的屏幕上运行,并在以后通过非交互式ssh命令启动后台作业时使用screen-r重新连接,需要关闭或以其他方式绑定stdin、stdout和stderr。否则,ssh将等待后台进程退出

这称为与控制终端解除关联或分离,是编写后台作业时的一般最佳实践,而不仅仅是针对SSH

因此,不使整个命令静音的最简单更改是添加:

#close std fds inherited from parent
close STDIN;
close STDOUT;
close STDERR;

就在您的
打印“输出已启动”;
之后。如果您的子进程在运行期间需要定期打印输出,则您需要重定向到日志文件。

为了更好地理解这一点,我建议您在上阅读@Jax的解决方案

这与Perl无关,这是因为SSH处理任何试图在后台运行的长时间进程的方式

我需要从bash脚本启动script.pl(在目标主机上定义基本的局部变量):

/path/to/launcher.sh使用以下命令调用Perl脚本:

CMD="/path/to/script.pl -some_arg=$VALUE -other_arg"
$CMD &
它在本地工作,但通过ssh运行时没有返回

我在Perl脚本中尝试了@pra的解决方案,但在我的例子中没有成功

使用@Jax的解决方案,我用以下内容替换了
$CMD&

nohup $CMD > /path/to/output.log 2>&1 < /dev/null &

nohup$CMD>/path/to/output.log 2>&1

它工作得很好。

这可以工作,返回控制。通过ssh远程运行它与本地运行它有什么不同?当它是本地运行时,它没有问题吗?@Razor,远程运行时,没有shell——另一端的ssh守护进程运行并将自身连接到脚本。您可能还可以实现您可以在ssh命令下运行
bash-c“perl script.pl”
,但是,父进程结束了,所以附加的守护进程不也应该停止运行吗?似乎没有任何效果。=[如果有人对这个问题有解决方案,而不是
screen
(我并不总是有可用的解决方案),我很想看。在阅读您的帖子之前,浪费了几个小时进行调试。谢谢,它很管用!
nohup $CMD > /path/to/output.log 2>&1 < /dev/null &