This answer介绍了使用Perl的exec()
时如何获取新进程的pid。 pid甚至都没有变化,因此您所需要做的就是获取原始脚本的pid。但是,如果我作为命令的一部分将输出重定向到文件,则该操作将无效。
say "my pid is $$";
exec("childscript.pl"); # same pid
但是如果我将输出重定向为命令的一部分:
say "my pid is $$";
exec("childscript.pl > log.txt"); # different pid, usually old pid + 1
exec("childscript.pl > log.txt 2>&1 &"); # same
然后,新的pid会比旧的pid高(这可能是因为它们是连续生成的并且不可靠)。我通过查看输出和在{childscript.pl“中插入sleep 30
来测试这一点,以便可以用ps -e
看到它。
我的猜测是重定向输出会导致一个新的过程来进行编写。但是我需要程序的pid,除了可以执行它之外,我对程序没有控制权。 (它也需要在后台运行。)
答案 0 :(得分:5)
当您使用单个参数调用exec
时(该参数包含shell元字符),perl会自动为您运行sh -c ARG
。就您而言:
exec("childscript.pl > log.txt");
# really means:
exec("/bin/sh", "-c", "childscript.pl > log.txt");
即您的脚本会将sh
加载到当前正在运行的进程中,并保持其PID。 Shell执行输出重定向,然后将childscript.pl
作为子进程(带有新的PID)运行。
有两种方法可以解决此问题:
在Perl中执行输出重定向,并且不生成外壳程序:
open STDOUT, ">", "log.txt" or die "$0: log.txt: $!\n";
exec "childscript.pl";
die "$0: childscript.pl: $!\n";
告诉外壳程序也使用exec
并且不产生子进程:
exec "exec childscript.pl > log.txt";
die "$0: childscript.pl: $!\n";