远程运行(通过ssh)时,perl fork无法正常工作 [英] perl fork doesn't work properly when run remotely (via ssh)

查看:87
本文介绍了远程运行(通过ssh)时,perl fork无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个perl脚本script.pl,该脚本在运行时会进行派生,父进程将其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控件调用它时,它永远不会返回到外壳程序(也从未打印过输出开始"行).

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

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

任何人都可以解释发生了什么事吗?

我在调试下运行它,并得到了它:

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

由于两个调试器争用相同的TTY,因此输入会被严重纠缠.

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

在类似UNIX的系统上,可以获取给定窗口的TTY名称 通过输入tty,并通过睡眠1000000断开外壳与TTY的连接.

解决方案

每当通过非交互式ssh命令启动后台作业时,都需要关闭或以其他方式阻止stdin,stdout和& stderr.否则,ssh将等待后台进程退出. 常见问题解答.. >

这称为与控制终端解除关联或分离,这是编写后台作业(不仅限于SSH)​​时的一般最佳做法.

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

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

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

I have a perl script, script.pl which, when run, does a fork, the parent process outputs its pid to a file then exits while the child process outputs something to STOUT and then goes into a while loop.

$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
    }
}

This works fine when I call it locally ie: perl script.pl.

The script prints out some things then returns control back to the shell. (while the child process goes off into its loop in the background).

However, when I call this via ssh control is never returned back to the shell (nor is the "Output started" line ever printed.

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

However, the interesting thing is, the child process does run (I can see it when I type ps).

Can anyone explain whats going on?

EDIT:

I ran it under debug and got this:

### Forked, but do not know how to create a new TTY.

Since two debuggers fight for the same TTY, input is severely entangled.

I know how to switch the output to a different window in xterms and OS/2 consoles only. For a manual switch, put the name of the created TTY in $DB::fork_TTY, or define a function DB::get_fork_TTY() returning this.

On UNIX-like systems one can get the name of a TTY for the given window by typing tty, and disconnect the shell from TTY by sleep 1000000.

解决方案

Whenever you launch background jobs via non-interactive ssh commands, you need to close or otherwise tie off stdin, stdout, & stderr. Otherwise ssh will wait for the backgrounded process to exit. FAQ.

This is called disassociating or detaching from the controlling terminal and is a general best practice when writing background jobs, not just for SSH.

So the simplest change that doesn't mute your entire command is to add:

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

right after your print "Output started";. If your child process needs to print output periodically during its run, then you'll need to redirect to a log file instead.

这篇关于远程运行(通过ssh)时,perl fork无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆