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

时间:2010-06-22 20:57:20

标签: perl unix ssh fork

我有一个perl脚本script.pl,当运行时,它会执行一个fork,父进程将其pid输出到一个文件,然后在子进程向STOUT输出内容然后进入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
    }
}

当我在本地调用它时,这工作正常,即:perl script.pl。

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

然而,当我通过ssh控制它时,控件永远不会返回到shell(也不会打印出“Output started”行。

即: $ ssh username@example.com'perl script.pl'

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

任何人都可以解释最新情况吗?

编辑:

我在调试下运行它得到了这个:

###分叉,但不知道如何创建新的TTY。

由于两个调试器争用相同的TTY,输入严重纠缠。

我知道如何在xterms中将输出切换到不同的窗口   和OS / 2控制台。对于手动切换,请输入已创建的TTY的名称   在$ DB :: fork_TTY中,或定义一个函数DB :: get_fork_TTY()返回此。

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

4 个答案:

答案 0 :(得分:9)

每当您通过非交互式ssh命令启动后台作业时,您需要关闭或以其他方式绑定stdin,stdout和&标准错误。否则ssh将等待后台进程退出。 FAQ

这称为取消与控制终端的关联或分离,是编写后台作业时的一般最佳做法,而不仅仅是SSH。

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

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

print "Output started";之后。如果您的子进程需要在运行期间定期打印输出,那么您将需要重定向到日志文件。

答案 1 :(得分:4)

ssh username@example.com 'nohup perl script.pl'

您无法退出,因为仍然附加了一个流程。您需要nohup

答案 2 :(得分:2)

正在发生的事情是ssh直接执行'perl script.pl'作为命令。如果你有“屏幕”,你可以这样做:

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

让它在分离的屏幕上运行,稍后使用screen -r

重新连接

答案 3 :(得分:0)

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

Getting ssh to execute a command in the background on target machine

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

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

$ ssh username@example.com /path/to/launcher.sh

/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 &

而且效果很好。