我怎样才能得到以这种方式启动的进程的pid

我怎样才能得到以这种方式启动的进程的pid
#!/bin/bash

mkfifo /var/run/out
while true
do
    cat /var/run/out | nc -l 8080 > >(
        while read line
        do
            do some stuff
        done
    )
done

nc我怎样才能得到和的 pid cat?使用 $!不起作用。我想将它们写入 pid 文件。

答案1

可能有一种更优雅的方式来做你想做的事,但这有效:

do
    (cat /var/run/out& echo $! > cat_pid; wait) |
                            (nc -l 8080 <&0 & echo $! > nc_pid; wait) > >(

(为了便于阅读,在 后面分成单独的行|)。其工作原理是将您想要的 PID 的每个命令包装在子 shell 中,在该子 shell 中异步运行它,捕获其 PID,然后等待命令完成。 (实际上,这会将命令放回到前台。)使用斯科特的 <&0在脚本中获取异步进程以读取其正确的标准输入的技巧。

你为什么用“猫”?和你为什么使用> >(…)而不是简单的管道

您可以将其简化为:

虽然是真的
    (nc -l 8080 < /var/run/out & echo $! > nc_pid; 等待) |
                读取行时
                    做一些事情
                完毕
完毕

nc直接读取/var/run/out,并使用简单的管道而不是进程替换。

答案2

我能想到的最简单的方法是在启动进程之前获取 pid。

例如(在 bash 中):

pidfile() { (
    echo $BASHPID > "$1"
    shift
    exec "$@"
) }

mkfifo /var/run/out
while true
do
    pidfile /tmp/cat.pid cat /var/run/out | pidfile /tmp/nc.pid nc -l 8080 > >(
        while read line
        do
            do some stuff
        done
    )
done

这将创建一个pidfile函数,将当前 PID 写入指定文件,然后使用 执行其余参数exec。这exec会导致命令以与刚刚写出文件的 shell 相同的 pid 运行。

我们将整个pidfile()函数括在括号内(),以便确保它在子 shell 中执行。当您执行不在管道中的命令时,这一点变得至关重要。例如:

pidfile /tmp/foo some command here

当您这样做时,pidfile()将与脚本的其余部分在同一进程中运行,因此当它调用 时exec,正在运行的命令将接管 PID,并且脚本将不再运行。

另请注意,以上内容都是为 bash 编写的。$BASHPID是 bash 特定的变量。$$使用子 shell 时不会改变,因此该值不适合我们的使用。

答案3

cat您无法获取或 的PIDnc 在那个脚本中除非你后台进程&。任何您不后台的进程都必须后台结束在脚本继续之前。

Bash wiki 进程管理文章解释了如何明智地做这些事情。

相关内容