如何获取通过管道传输到 Bash 中另一个进程的进程的 PID?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1652680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:38:33  来源:igfitidea点击:

How to get the PID of a process that is piped to another process in Bash?

bashpipepid

提问by Ertu? Karamatl?

I am trying to implement a simple log server in Bash. It should take a file as a parameter and serve it on a port with netcat.

我正在尝试在 Bash 中实现一个简单的日志服务器。它应该将一个文件作为参数并通过 netcat 在端口上提供它。

( tail -f  & ) | nc -l -p 9977

But the problem is that when the netcat terminates, tail is left behind running. (Clarification: If I don't fork the tail process it will continue to run forever even the netcat terminates.)

但问题是当 netcat 终止时,tail 会留在后面运行。(澄清:如果我不 fork 尾部进程,即使 netcat 终止,它也将永远运行。)

If I somehow know the PID of the tail then I could kill it afterwards.
Obviously, using $! will return the PID of netcat.

如果我以某种方式知道尾部的 PID,那么我可以在之后杀死它。
显然,使用 $! 将返回netcat的PID。

How can I get the PID of the tail process?

如何获得尾部进程的PID?

采纳答案by bobbogo

Write tail's PID to file descriptor 3, and then capture it from there.

将 tail 的 PID 写入文件描述符 3,然后从那里捕获它。

( tail -f  & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)

回答by VladV

Another option: use a redirect to subshell. This changes the order in which background processes are started, so $! gives PID of the tailprocess.

另一种选择:使用重定向到子shell。这会改变后台进程启动的顺序,所以 $! 给出tail进程的PID 。

tail -f  > >(nc -l -p 9977) &
wait $!

回答by przemas

how about this:

这个怎么样:

jobs -x echo %1

%1is for first job in chain, %2for second, etc. jobs -xreplaces job specifier with PID.

%1用于链中的第一个作业,%2用于第二个等jobs -x。用 PID 替换作业说明符。

回答by James Shau

This works for me (SLES Linux):

这对我有用(SLES Linux):

tail -F xxxx | tee -a yyyy &
export TAIL_PID=`jobs -p`
# export TEE_PID="$!"

The ps|grep|killtrick mentioned in this thread would not work if a user can run the script for two "instances" on the same machine.

ps|grep|kill如果用户可以在同一台机器上为两个“实例”运行脚本,则此线程中提到的技巧将不起作用。

jobs -x echo %1did not work for me (man page not having the -xflag) but gave me the idea to try jobs -p.

jobs -x echo %1对我不起作用(手册页没有-x标志)但给了我尝试的想法jobs -p

回答by martin clayton

Maybe you could use a fifo, so that you can capture the pid of the first process, e.g.:

也许您可以使用fifo,以便您可以捕获第一个进程的 pid,例如:

FIFO=my_fifo

rm -f $FIFO
mkfifo $FIFO

tail -f  > $FIFO &
TAIL_PID=$!

cat $FIFO | nc -l -p 9977

kill $TAIL_PID

rm -f $FIFO

回答by pjil

ncatautomatically terminates tail -fon exit (on Mac OS X 10.6.7)!

ncattail -f退出时自动终止(在 Mac OS X 10.6.7 上)!

# simple log server in Bash using ncat
# cf. http://nmap.org/ncat/
touch file.log
ncat -l 9977 -c "tail -f file.log" </dev/null   # terminal window 1
ncat localhost 9977 </dev/null                  # terminal window 2
echo hello > file.log                           # terminal window 3

回答by Ertu? Karamatl?

Finally, I have managed to find the tail process using ps. Thanks to the idea from ennuikiller.

最后,我设法使用ps. 感谢 ennukiller 的想法。

I have used the psto grep tail from the args and kill it. It is kind of a hack but it worked. :)

我已经使用了ps从 args 中 grep tail 并杀死它。这有点像黑客,但它奏效了。:)

If you can find a better way please share.

如果你能找到更好的方法,请分享。

Here is the complete script:
(Latest version can be found here: http://docs.karamatli.com/dotfiles/bin/logserver)

这是完整的脚本:(
最新版本可以在这里找到:http: //docs.karamatli.com/dotfiles/bin/logserver

if [ -z "" ]; then
    echo Usage: 
coproc TAIL { tail -f ; }; exec {TAIL[1]}<&-
coproc NC { nc -v -l -p 9977; } <&"${TAIL[0]}" >&1
wait $NC_PID; echo "nc exit code: $!"
kill $TAIL_PID; echo "done"
LOGFILE [PORT] exit -1 fi if [ -n "" ]; then PORT= else PORT=9977 fi TAIL_CMD="tail -f " function kill_tail { # find and kill the tail process that is detached from the current process TAIL_PID=$(/bin/ps -eo pid,args | grep "$TAIL_CMD" | grep -v grep | awk '{ print }') kill $TAIL_PID } trap "kill_tail; exit 0" SIGINT SIGTERM while true; do ( $TAIL_CMD & ) | nc -l -p $PORT -vvv kill_tail done

回答by pipe_of_sharks

You could use the coproccommand twice.

您可以使用该coproc命令两次。

The given example translates to:

给定的示例转换为:

# terminal window 1
# using nc on Mac OS X (FreeBSD nc)
: > /tmp/foo
PID=$( { { tail -f /tmp/foo 0<&4 & echo $! >&3 ; } 4<&0 | { nc -l 9977 ;} & } 3>&1 | head -1 )
kill $PID

# terminal window 2
nc localhost 9977

# terminal window 3
echo line > /tmp/foo

(I've thrown a -vand a couple echoin there for troubleshooting.)

(我已经在那里扔了-v一对夫妇echo进行故障排除。)

Using coprocfeels a lot like using Popen() in various other scripting languages.

使用coproc感觉很像在其他各种脚本语言中使用 Popen() 。

回答by chad

You may store the pid of the tailcommand in a variable using Bash I/O redirections only (see How to get the PID of a process in a pipeline).

您可以tail仅使用 Bash I/O 重定向将命令的 pid 存储在变量中(请参阅如何获取管道中进程的 PID)。

nc -l -p 9977 -c "tail -f "

回答by Paused until further notice.

Have you tried:

你有没有尝试过:

##代码##

(untested)

(未经测试)

Or -ewith a scriptfile if your ncdoesn't have -c. You may have to have an ncthat was compiled with the GAPING_SECURITY_HOLEoption. Yes, you should infer appropriate caveats from that option name.

或者-e如果你nc没有-c. 您可能必须有一个nc使用该GAPING_SECURITY_HOLE选项编译的。是的,您应该从该选项名称中推断出适当的警告。