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