从另一个环境调用时在后台运行的 Perl
Perl on background when invoked from another env
我有一个 Perl 脚本应该在后台做一些工作。描述得很好——我 fork,kill (return 0) parent 并在 child 中完成工作。当我直接从 shell 运行 它时,它会按预期工作(即 return 在杀死 parent 后立即到 shell 并在后台继续)。但是如果我 运行 它来自另一个环境,例如从 PHP 通过执行
php -r "passthru('my-perl-script.pl')"
在 child 完成后,它 return 到 shell。知道为什么会这样吗?
谢谢!
编辑:
这是我使用的 Perl 代码:
#!/usr/bin/env perl
use strict;
use warnings;
local $| = 1;
# fork the process - returns child pid to the parent process and 0
# to the child process
print ' [FORKING] ';
my $pid = fork();
error('Failed to fork: $@') and exit 1 if $@;
# exit parent
print ' [KILLING PARENT] ';
exit 0 if $pid;
# continue as child process
print " [CONTINUING AS CHILD] \n";
# wait 3 secs (for testing) and exit
sleep 3;
print " [DONE]\n";
exit 1;
直接执行输出:
$ ./background-test.pl
[FORKING] [KILLING PARENT] [KILLING PARENT] [CONTINUING AS CHILD]
$ [DONE]
通过PHP执行时的输出:
$ php -r "system('./background-test.pl');"
$ [FORKING] [KILLING PARENT] [KILLING PARENT] [CONTINUING AS CHILD]
# ... 3 seconds wait ...
[DONE]
$
我的问题是为什么 Perl 脚本在从其他环境调用时不断开连接(这里 PHP 只是一个例子)。
谢谢!
如果我没理解错的话,你是说 PHP 正在等待盛大 child 结束,即使 child 已经退出。
system
不会 return,因为 php
收集 child 的 STDOUT,与 grandchild 继承的相同 STDOUT。在 Linux 系统上,可以通过将以下内容添加到 Perl 脚本中来查看:
system("ls -l /proc/$$/fd");
来自shell:
lrwx------ 1 ikegami ikegami 64 Jun 1 14:07 1 -> /dev/pts/0
来自PHP:
l-wx------ 1 ikegami ikegami 64 Jun 1 14:08 1 -> pipe:[10052926]
通常情况下,当你去守护进程时,你会重新打开它的 STDIN、STDOUT 和 STDERR,将它们重定向到 /dev/null
或日志文件。
open(STDIN, '<', '/dev/null') or die $!;
open(STDOUT, '>', '/dev/null') or die $!;
open(STDERR, '>>', '/var/log/application.log') or die $!;
通常情况下,当你去守护一个进程时,你也会调用POSIX::setsid()
。
我有一个 Perl 脚本应该在后台做一些工作。描述得很好——我 fork,kill (return 0) parent 并在 child 中完成工作。当我直接从 shell 运行 它时,它会按预期工作(即 return 在杀死 parent 后立即到 shell 并在后台继续)。但是如果我 运行 它来自另一个环境,例如从 PHP 通过执行
php -r "passthru('my-perl-script.pl')"
在 child 完成后,它 return 到 shell。知道为什么会这样吗?
谢谢!
编辑: 这是我使用的 Perl 代码:
#!/usr/bin/env perl
use strict;
use warnings;
local $| = 1;
# fork the process - returns child pid to the parent process and 0
# to the child process
print ' [FORKING] ';
my $pid = fork();
error('Failed to fork: $@') and exit 1 if $@;
# exit parent
print ' [KILLING PARENT] ';
exit 0 if $pid;
# continue as child process
print " [CONTINUING AS CHILD] \n";
# wait 3 secs (for testing) and exit
sleep 3;
print " [DONE]\n";
exit 1;
直接执行输出:
$ ./background-test.pl
[FORKING] [KILLING PARENT] [KILLING PARENT] [CONTINUING AS CHILD]
$ [DONE]
通过PHP执行时的输出:
$ php -r "system('./background-test.pl');"
$ [FORKING] [KILLING PARENT] [KILLING PARENT] [CONTINUING AS CHILD]
# ... 3 seconds wait ...
[DONE]
$
我的问题是为什么 Perl 脚本在从其他环境调用时不断开连接(这里 PHP 只是一个例子)。
谢谢!
如果我没理解错的话,你是说 PHP 正在等待盛大 child 结束,即使 child 已经退出。
system
不会 return,因为 php
收集 child 的 STDOUT,与 grandchild 继承的相同 STDOUT。在 Linux 系统上,可以通过将以下内容添加到 Perl 脚本中来查看:
system("ls -l /proc/$$/fd");
来自shell:
lrwx------ 1 ikegami ikegami 64 Jun 1 14:07 1 -> /dev/pts/0
来自PHP:
l-wx------ 1 ikegami ikegami 64 Jun 1 14:08 1 -> pipe:[10052926]
通常情况下,当你去守护进程时,你会重新打开它的 STDIN、STDOUT 和 STDERR,将它们重定向到 /dev/null
或日志文件。
open(STDIN, '<', '/dev/null') or die $!;
open(STDOUT, '>', '/dev/null') or die $!;
open(STDERR, '>>', '/var/log/application.log') or die $!;
通常情况下,当你去守护一个进程时,你也会调用POSIX::setsid()
。