#!/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 进程管理文章解释了如何明智地做这些事情。