如何获取一个进程的PID到Bash中的另一个进程?
我正在试图在Bash中实现一个简单的日志服务器。 它应该把一个文件作为参数,并通过netcat在一个端口上提供。
( tail -f $1 & ) | nc -l -p 9977
但是问题是,当netcat终止时,尾部被遗忘运行。 (澄清:如果我不分叉尾部进程,它将继续运行,即使netcat终止。)
如果我以某种方式知道尾巴的PID,那么我可以在之后杀死它。
显然,使用$! 将返回netcat的PID。
我怎样才能得到尾部进程的PID?
将尾部的PID写入文件描述符3,然后从那里捕获。
( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977 kill $(<pid)
另一个select:使用redirect到subshell。 这改变了后台进程开始的顺序,所以$! 给出tail
过程的PID。
tail -f $1 > >(nc -l -p 9977) & wait $!
这个怎么样:
jobs -x echo %1
%1
代表链中的第一份工作, %2
代表第二份等等。 jobs -x
用PID代替作业说明符。
这适用于我(SLES Linux):
tail -F xxxx | tee -a yyyy & export TAIL_PID=`jobs -p` # export TEE_PID="$!"
如果用户可以在同一台机器上运行两个“实例”的脚本,则此线程中提到的ps|grep|kill
技巧将不起作用。
jobs -x echo %1
没有为我工作(手册页没有-x
标志),但给了我想法尝试jobs -p
。
也许你可以使用fifo ,这样你可以捕获第一个进程的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
最后,我设法使用ps
find了尾部进程。 感谢ennuikiller的想法。
我已经用ps
从greg尾巴,并杀死它。 这是一种黑客,但它的工作。 🙂
如果你能find更好的方式,请分享。
这是完整的脚本:
(最新版本可以在这里find: http : //docs.karamatli.com/dotfiles/bin/logserver )
if [ -z "$1" ]; then echo Usage: $0 LOGFILE [PORT] exit -1 fi if [ -n "$2" ]; then PORT=$2 else PORT=9977 fi TAIL_CMD="tail -f $1" 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 $1 }') kill $TAIL_PID } trap "kill_tail; exit 0" SIGINT SIGTERM while true; do ( $TAIL_CMD & ) | nc -l -p $PORT -vvv kill_tail done
ncat
在退出时自动终止tail -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
一种方法是简单地用你的脚本ppid做一个ps -ef和grep
你有没有尝试过:
nc -l -p 9977 -c "tail -f $1"
(另)
或者如果您的nc
没有-c
,则使用脚本文件。 您可能需要使用GAPING_SECURITY_HOLE
选项编译的nc
。 是的,你应该从该选项名称推断适当的警告。
您可以使用Bash I / Oredirect将tail
命令的pid存储在一个variables中(请参阅如何获取stream水线中进程的PID )。
# 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
不是一个理想的答案,但我find了一个解决scheme,我工作的logging器守护进程:
#!/bin/sh tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error
从$信息尾巴:
--pid=PID with -f, terminate after process ID, PID dies
尾巴的–pid选项是你最好的朋友。 它将允许您完全控制在后台运行的pipe道。 阅读tail命令选项以获得更大的恢复能力,以防您的文件被另一个进程主动旋转,从而导致您无用的inode。 下面的例子虽然没有用来处理数据,但是certificate了对尾部的“强加”限制以及随时告诉它退出的能力。 这用于测量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