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

时间:2018-12-22 19:21:25

标签: perl pid

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,除了可以执行它之外,我对程序没有控制权。 (它也需要在后台运行。)

1 个答案:

答案 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)运行。

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

  1. 在Perl中执行输出重定向,并且不生成外壳程序:

    open STDOUT, ">", "log.txt" or die "$0: log.txt: $!\n";
    exec "childscript.pl";
    die "$0: childscript.pl: $!\n";
    
  2. 告诉外壳程序也使用exec并且不产生子进程:

    exec "exec childscript.pl > log.txt";
    die "$0: childscript.pl: $!\n";