2014-05-12 85 views
4

(或如何殺死子進程)?如何獲得管道命令的pid?

inotifywait -mqr --format '%w %f %e' $feedDir | while read dir file event 
do 
#something 
done & 

echo $! #5431 

PS例如:

>$ ps 
    PID TTY   TIME CMD 
2867 pts/3 00:00:02 bash 
5430 pts/3 00:00:00 inotifywait 
5431 pts/3 00:00:00 bash 
5454 pts/3 00:00:00 ps 

看來,如果我殺瞭然後(inotifywait)將保持運行,但如果我殺瞭然後兩個進程死亡。我不認爲我能夠可靠地認爲inotifywait的pid始終小於$!

+0

確定$$是5431?我認爲5431就是你在管道里進入的時候。 – yaccz

+0

我肯定希望$$低於inotifywait的pid,除非包含pid數字,然後它們會緊挨着彼此(±1)的機率很渺茫 – yaccz

+0

非常確定,我手動鍵入'echo $$'後跟'ps'的輸出結果與發佈時一模一樣 – andrew

回答

2

當我們運行一個管道時,每個命令都在一個獨立的進程中執行。口譯員等待最後一個,但如果我們使用&符號(&)。

cmd1 | cmd2 & 

進程的PID可能會接近,但我們不能認爲它是可靠的。在最後一個命令是bash保留字的情況下,它會創建一個專用的bash(這就是爲什麼您的'dir','文件'變量在done關鍵字後不會存在的原因)。示例:

ps # shows one bash process 
echo "azerty" | while read line; do ps; done # shows one more bash 

當第一個命令退出時,第二個命令將終止,因爲管道上的讀取返回EOF。 當第二個命令退出時,第一個命令將在試圖寫入管道時由signal SIGPIPE(在沒有閱讀器的管道上寫入)終止。但是如果命令無限期地等待......它不會被終止。

echo「$!」打印在後臺執行的最後一個命令的pid。在你的情況下,執行while循環的bash進程。

您可以使用以下語法找到「inotifywait」的pid。但它uggly:

(inotifywait ... & echo "$!">inotifywait.pid) | \ 
while read dir file event 
do 
    #something 
done & 
cat inotifywait.pid # prints pid of inotifywait 

如果你不想PID,只是可以肯定的過程將被終止,您可以中使用inotifywait的-t選項:這

(while true; do inotifywait -t 10 ...; done)| \ 
while read dir file event 
do 
    #something 
done & 
kill "$!" # kill the while loop 

無解決方案很好。你真正的成就是什麼?也許我們可以找到更優雅的解決方案。

0

如果你的目標是確保所有的孩子可以被殺死或打斷優雅。如果您使用的是BusyBox的Ash,則不需要進行流程替換。如果您不想使用fd,請查看此解決方案。

#!/bin/sh 

pid=$$ 

terminate() { 
    pkill -9 -P "$pid" 
} 

trap terminate SIGHUP SIGINT SIGQUIT SIGTERM 

# do your stuff here, note: should be run in the background {{{ 
inotifywait -mqr --format '%w %f %e' $feedDir | while read dir file event 
do 
#something 
done & 
# }}} 

# Either pkill -9 -P "$pid" here 

wait 

# or pkill -9 -P "$pid" here 

或者在另一個shell:

kill <pid ($$)> 
+1

'陷阱終止SIGHUP SIGINT SIGQUIT SIGTERM'(除非你是由行支付...) –

+0

我不知道我能做到這一點。謝謝! – changyuheng

+0

當然,很高興它有幫助。幫助保持事物的美好和整潔。 –