【发布时间】:2017-01-15 19:23:32
【问题描述】:
因此,我在 mod_perl 脚本中使用 Proc::Daemon:
$bindir, $ddir 是可执行文件/日志文件的位置,$jid 是每个进程的唯一标识符(以避免多个进程打开同一个文件)。 $cmd 加载了任意 perl 脚本和参数。
my $daemon = Proc::Daemon->new (
work_dir => $bindir,
child_STDOUT => $ddir.'/'.$jid.'_stdout.log',
child_STDERR => $ddir.'/'.$jid.'_stderr.log',
pid_file => $ddir.'/'.$jid.'_pid.txt',
exec_command => $cmd,
);
my $pid = $daemon->Init();
在将 Apache 与 cgi-script(无 mod_perl)一起使用时,上述内容可以正常工作。在“$cmd”进程中,打印STDERR日志并将其打印到上面定义的日志文件中。
当我在 Ubuntu Linux 14.04 LTS 上使用 Apache2 使用 mod_perl2 运行上述程序时,使用 PID 写入 pid 文件并创建上述日志文件,但没有任何内容写入日志文件。我可以在 $cmd 中打开新的文件描述符并写入它们,但在 mod_perl 下,它不会将输出发送到 child_STDOUT 和 child_STDERR 文件。
我认为我遗漏了一些非常明显的东西。有没有其他人以前见过这个,或者有任何建议让它在 mod_perl 中工作。
附加信息 在 Apache 中使用 mpm_prefork 模块
相关的 Apache 配置
<Files "*.pl">
# SetHandler cgi-script # It works if I use cgi-script
SetHandler perl-script
PerlOptions -SetupEnv # Tried with and without this
# PerlHandler ModPerl::RegistryPrefork # Using this made no difference
PerlHandler ModPerl::Registry
</Files>
【问题讨论】:
-
它可能假设
fileno(STDOUT)是 2(等等),但它不是,或者过于特殊。 -
我认为这是一个很好的假设,但它在 Proc::Daemon 页面中说,第二个孩子关闭所有打开的文件描述符(除非您定义 dont_close_fh 和/或 dont_close_fd)。第二个孩子打开 STDIN、STDOUT 和 STDERR 到构造函数中定义的位置(新)。所以它应该关闭所有文件描述符,然后打开新的。也许 mod_perl 以某种方式改变了 STDIN/STDOUT 的全局常量??
-
我不会认为这与我所说的相矛盾,尤其是因为它是根据 STDOUT 而不是 fd 2 说话的。
-
是的,不一定是矛盾的,更多附加信息。有趣的是 Proc::Daemon 应该关闭子进程中的所有文件句柄,然后打开新的文件句柄,这意味着它不应该关心 STDIN/OUT 是否为 0/1 它应该只关闭它们,然后打开新的。有趣的附加说明,如果我使用 SetHandler modperl 而不是 SetHandler perl-script,在子进程中打印和打印 STDERR 会转到指定的日志文件,但随后在常规的非分叉脚本中打印不再连接到浏览器。跨度>
-
两者之间的区别之一是 perl-script 执行以下操作:STDIN 和 STDOUT 绑定到请求对象 $r,这使得从 STDIN 读取并通过 CORE 直接打印到 STDOUT 成为可能::print(),而不是像 $r->puts() 这样的隐式调用。所以我想问题是,我如何为子进程解开这些,但将配置留给父进程?我可能会自己动手卷叉,但我宁愿不这样做,我喜欢 Proc::Daemon 的整体易用性。
标签: linux perl apache2 mod-perl2 mod-perl-registry