如何获取在Perl脚本中执行的程序的PID

fel*_*the 2 perl pid

这个答案解释了如何在使用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,除了我可以执行它之外我无法控制程序.(它也需要在后台运行.)

mel*_*ene 5

当您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).

有两种方法可以解决此问题:

  1. 在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)
  2. 告诉shell也使用exec而不是生成子进程:

    exec "exec childscript.pl > log.txt";
    die "$0: childscript.pl: $!\n";
    
    Run Code Online (Sandbox Code Playgroud)