我想在Bash中實現一個簡單的日誌服務器。它應該將一個文件作爲參數並通過netcat在端口上提供。如何獲取一個進程在Bash中的另一個進程的PID?
(tail -f $1 &) | nc -l -p 9977
但問題是,當netcat終止時,尾部留下運行。 (澄清:如果我不分叉尾部進程,它將繼續運行,即使netcat終止。)
如果我以某種方式知道尾部的PID,那麼我可以在之後殺死它。
顯然,使用$!將返回netcat的PID。
如何獲得尾部過程的PID?
我想在Bash中實現一個簡單的日誌服務器。它應該將一個文件作爲參數並通過netcat在端口上提供。如何獲取一個進程在Bash中的另一個進程的PID?
(tail -f $1 &) | nc -l -p 9977
但問題是,當netcat終止時,尾部留下運行。 (澄清:如果我不分叉尾部進程,它將繼續運行,即使netcat終止。)
如果我以某種方式知道尾部的PID,那麼我可以在之後殺死它。
顯然,使用$!將返回netcat的PID。
如何獲得尾部過程的PID?
一種方法是簡單地做尾PS -ef和grep與你的腳本PPID
我無法使用ppid獲取它,因爲當我將它分叉到子殼中時它會分離。但我設法使用'ps'程序的參數param來對其進行grep。 – 2009-10-31 12:02:00
也許你可以使用一個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
是的,我曾嘗試過。關於使用fifo的問題是相同的:管道永遠不會終止,因此即使netcat終止,cat仍然運行。此外,控制停留在貓行,所以它從不執行殺死。 – 2009-10-31 09:25:30
這很奇怪 - 上面的腳本在Mac OS X上完全適用於我。只是略有不同,我省略了'-p'標誌。 – 2009-10-31 10:06:04
也許它是一個平臺問題(關於如何處理管道)。我正在linux機器上嘗試它。無論如何感謝您的回答! – 2009-10-31 10:17:04
你試過:
nc -l -p 9977 -c "tail -f $1"
(未經測試)
或-e
與腳本文件如果您的nc
沒有-c
。您可能必須具有使用GAPING_SECURITY_HOLE
選項編譯的nc
。是的,你應該從該選項名稱推斷出適當的警告。
哦,我從來沒有想過它。我希望它的工作:) 但它仍然沒有終止,因爲「tail -f」的性質 – 2009-10-31 10:19:51
沒有'-f'怎麼辦?沒有-f, – 2009-10-31 10:27:52
。但我想實時提供服務。 – 2009-10-31 10:36:55
最後,我設法找到使用ps
的尾部過程。感謝ennuikiller的想法。
我已經使用了ps
grep尾巴從args和殺死它。這是一種黑客,但它的工作。 :)
如果你能找到更好的方式,請分享。
下面是完整的腳本:
(最新版本可以在這裏找到: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
不應該在'$!'中使用tail命令的PID,以便您可以簡單地執行kill $!而不是kill_tail? – tripleee 2011-09-19 09:30:46
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
您可能使用bash I/O重定向只(見How to get the PID of a process in a pipeline)存儲tail
命令的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
另一種選擇:使用重定向到subshell。這改變了後臺進程開始的順序,所以$!給出了tail
進程的PID。
tail -f $1 > >(nc -l -p 9977) &
wait $!
這個怎麼樣:
jobs -x echo %1
%1
是在鏈的第一份工作,%2
爲第二等jobs -x
替換工作說明符PID。
這必須是「如何在鏈中更早獲得任何進程的PID」的最簡潔+最短的解決方案。謝謝!它也適用於'&'在後臺運行的鏈中獲取進程的pid!例如。 'dd if =/dev/urandom bs = 1M count = 1024 | sha1sum&pid = $(jobs - x echo%1)' 'kill -USR1 $ pid' – JATothrim 2014-11-29 12:05:32
不是一個理想的答案,但我發現一個日誌守護進程,我在工作了解決方法:
#!/bin/sh
tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error
從$信息尾:
--pid=PID
with -f, terminate after process ID, PID dies
這對我的作品(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
。
尾巴的--pid選項是你最好的朋友。它將允許您完全控制在後臺運行的管道。閱讀tail命令選項以獲得更大的恢復能力,以防您的文件被另一個進程主動輪換,這可能會導致您拖尾處於非活動狀態的inode。下面的例子雖然沒有用於處理數據,但它表明了對尾部的「強加」限制和告訴它隨時退出的能力。這用於測量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
如果不使用'&'會怎麼樣? 'tail -f'應該等在那裏。我不明白''是什麼,儘管它看起來像是一個更大腳本的一部分。無論如何,如果你殺了菸斗,我會認爲尾巴會死(只要你沒有背景)。 – 2013-05-22 05:11:21
來自我對殼的理解,在這種情況下,它的含義是「從開始到背景」。至少,這就是我現在看到的行爲,試圖將解決方案應用於我自己的類似問題。 – starturtle 2016-07-07 11:02:16