如何在Bash中获取通过管道传输到另一个进程的进程的PID?
我试图在Bash中实现一个简单的日志服务器。它应该将一个文件作为参数,并在netcat的端口上提供该文件如何在Bash中获取通过管道传输到另一个进程的进程的PID?,bash,pipe,pid,Bash,Pipe,Pid,我试图在Bash中实现一个简单的日志服务器。它应该将一个文件作为参数,并在netcat的端口上提供该文件 ( tail -f $1 & ) | nc -l -p 9977 但问题是,当netcat终止时,tail就没有运行了。(澄清:如果我不分叉尾部进程,即使netcat终止,它也将永远运行。) 如果我知道尾巴的PID,我可以在事后杀死它。 显然,使用$!将返回netcat的PID 如何获取tail进程的PID?一种方法是简单地使用脚本ppid执行ps-ef和grep for tail
( tail -f $1 & ) | nc -l -p 9977
但问题是,当netcat终止时,tail就没有运行了。(澄清:如果我不分叉尾部进程,即使netcat终止,它也将永远运行。)
如果我知道尾巴的PID,我可以在事后杀死它。显然,使用$!将返回netcat的PID
如何获取tail进程的PID?一种方法是简单地使用脚本ppid执行ps-ef和grep for tail也许您可以使用,以便捕获第一个进程的PID,例如:
FIFO=my_fifo
rm -f $FIFO
mkfifo $FIFO
tail -f $1 > $FIFO &
TAIL_PID=$!
cat $FIFO | nc -l -p 9977
kill $TAIL_PID
rm -f $FIFO
您是否尝试过:
nc -l -p 9977 -c "tail -f $1"
(未经测试)
或者如果您的
nc
没有-c
,则使用脚本文件-e
。您可能需要使用GAPING\u SECURITY\u HOLE
选项编译一个nc
。是的,您应该从该选项名称推断出适当的注意事项。最后,我使用ps
找到了尾部进程。多亏了ennuikiller的创意
我使用了ps
从args中grep tail并杀死它。这有点像黑客,但它奏效了。:)
如果你能找到更好的方法,请分享
以下是完整的脚本:(最新版本可在此处找到:)
将tail的PID写入文件描述符3,然后从那里捕获它
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
(tail-f$1&echo$!>&3)3>pid | nc-l-p9977
kill$(ncat
在退出时自动终止tail-f
(在Mac OS X 10.6.7上)
#Bash中使用ncat的简单日志服务器
#比照。http://nmap.org/ncat/
touch file.log
ncat-l 9977-c“tail-f file.log”您可以仅使用Bash I/O重定向将tail
命令的pid存储在变量中(请参阅)
#终端窗口1
#在Mac OS X上使用nc(FreeBSD nc)
:>/tmp/foo
PID=$({tail-f/tmp/foo 0&3;}4&1 | head-1)
杀死$PID
#终端窗口2
nc本地主机9977
#终端窗口3
回音线>/tmp/foo
另一个选项:使用重定向到subshell。这会更改后台进程的启动顺序,因此$!会给出尾部进程的PID
tail -f $1 > >(nc -l -p 9977) &
wait $!
这个怎么样:
jobs -x echo %1
%1
用于链中的第一个作业,%2
用于第二个作业,等等。作业-x
将作业说明符替换为PID。这不是一个理想的答案,但我找到了一个解决我使用的记录器守护程序的方法:
#!/bin/sh
tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error
从$info tail开始:
--pid=PID
with -f, terminate after process ID, PID dies
这适用于我(SLES Linux):
如果用户可以在同一台机器上为两个“实例”运行脚本,则此线程中提到的ps | grep | kill
技巧将不起作用
作业-x echo%1对我不起作用(手册页没有-x
标志)但是给了我一个尝试jobs-p
tail的--pid选项是您最好的朋友。它将允许您完全控制后台运行的管道。如果您的文件被另一个进程主动旋转,可能导致您跟踪一个不活动的inode,请阅读tail命令选项以获得更大的恢复力。例如低,尽管不用于处理数据,但证明了尾部的“强制”限制以及随时告知其退出的能力。这用于测量httpd上的工作压力
# Set the tail to die in 100 second even if we die unexpectedlly.
sleep 100 & ; ctlpid=$!
tail -q -n 0 --follow=name --retry --max-unchanged-stats=1 --pid=$ctlpid -f /var/log/httpd/access_log 2>/dev/null | wc –l > /tmp/thisSampleRate &
…. Do some other work
…. Can kill the pipe at any time by killing $ctlpid
…. Calculate preassure if /tmp/thisSampleRate is ready
您可以使用coproc
命令两次
给出的示例可转化为:
coproc TAIL { tail -f $1; }; 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"
coproc TAIL{TAIL-f$1;};exec{TAIL[1]}可以工作,但需要一个中介pid文件
您可以利用功能>()
,它的工作原理类似于|
,但无需等待tail
完成
tail -f $1 > >(nc -l -p 9977) & pid=!
是的,我以前试过。使用fifo的问题是一样的:管道永远不会终止,所以即使netcat终止,cat也会保持运行。控件也会保持在cat行中,所以它永远不会执行kill。这很奇怪-上面的脚本在Mac OS X上对我非常有效。唯一的细微区别是我忽略了nc的“-p”标志。也许这是一个错误平台问题(关于如何处理管道)。我正在linux机器上尝试它。无论如何谢谢你的回答!如果你删除cat
并使用nc-l-p9977<$FIFO
?哦,我从来没有想过。我希望它能工作:),但它仍然没有终止,因为“tail-f”的性质如果没有-f,就可以了。但我想实时提供它。我无法使用ppid获取它,因为当我在子shell中分叉它时它是分离的。但是我设法使用ps
程序的args参数grep它。tail命令的PID不应该在$!
中可用,这样你就可以简单地执行kill$!
关于kill_tail
?我使用了一个变体:(tail-f$1&echo$!>pid)| nc-l-p 9977
(不确定在最终重定向到文件时为什么使用文件描述符3会有帮助)不知道为什么,但我的解决方案在输出两行日志后失败。可能是在管道缓冲区已满时。然后初始进程似乎在等待管道被处理。如果不使用&
,会发生什么情况?tail-f
应该在那里等待。我不知道&
是用于什么,尽管它确实在那里这是一个更大的脚本的一部分。无论如何,如果你杀死了管道,我会认为尾巴会死(只要你没有背景)。根据我对shell的理解,在这个例子中,它的意思是“开始到背景”。至少,这是我现在看到的行为,试图将解决方案应用于我自己的类似问题。相关:此方法的优点是,在等待之后,$?还保持退出状态。这似乎是最干净的方法。它会改变什么(与标准管道相比)从启动顺序以外的任何一个进程的角度来看,实际上,重定向的语法是错误的(尽管
tail -F xxxx | tee -a yyyy &
export TAIL_PID=`jobs -p`
# export TEE_PID="$!"
# Set the tail to die in 100 second even if we die unexpectedlly.
sleep 100 & ; ctlpid=$!
tail -q -n 0 --follow=name --retry --max-unchanged-stats=1 --pid=$ctlpid -f /var/log/httpd/access_log 2>/dev/null | wc –l > /tmp/thisSampleRate &
…. Do some other work
…. Can kill the pipe at any time by killing $ctlpid
…. Calculate preassure if /tmp/thisSampleRate is ready
coproc TAIL { tail -f $1; }; 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"
tail -f $1 > >(nc -l -p 9977) & pid=!