Shell-Script

如何在同一個 shell 腳本中將一個程序的 PID 傳遞給另一個程序?

  • January 28, 2019

好的,所以這可能是一個非常愚蠢的問題,而且我不經常編寫 shell 腳本。我正在嘗試在後台啟動 3 個程序,在 shell 腳本中一個接一個地啟動,例如:

#!/bin/sh
PROCESS1 &
PROCESS2 &
PROCESS3 &

這是問題所在。我需要以與所示相同的順序啟動這些程序。此外,PROCESS2 的 PID 需要作為命令行參數傳遞給 PROCESS3。所有這些程序都在無限循環中執行,並且在 3 個單獨的終端中執行時它們確實可以順利執行。

我試過:

#!/bin/sh
PROCESS1 &
PROCESS2 &
PID_PROCESS2=$!
PROCESS3 ${PID_PROCESS2} &

這會啟動 PROCESS1 和 PROCESS3,但 PROCESS2 會立即退出而不會列印任何錯誤。它只是消失了。ps 命令它沒有顯示 PROCESS2 的痕跡。列印 PID_PROCESS2 會給出一些值“p”,並且 PROCESS3 以值“p”作為參數執行得很好。有什麼問題,我缺乏什麼?

可能很重要的細節

1)在上面的範例中,我使用限定路徑來呼叫各個程序,它們都是本機二進製文件並且位於同一目錄中。例如,

#!/bin/sh
/usr/bin/PROCESS1 &

ps的輸出如前所述,

$ps | grep "/path/to/PROCESS"
10064 root 16536 S /path/to/PROCESS1
10066 root 11084 S /path/to/PROCESS3 10065

這清楚地表明 PROCESS2 已啟動但由於某種未知原因退出。

2)PROCESS2 通過 FIFO(命名管道)與 PROCESS1 通信,這是一種單向通信。

解決方法

#/bin/sh
/path/to/PROCESS1 &
/path/to/PROCESS2 & PROCESS2_PID=$!
export P2PID=${PROCESS2_PID}
sh -c "/path/to/PROCESS3 ${P2PID}"

這似乎通過一個額外的 sh 程序來完成這項工作。

$ps | grep "/path/to/PROCESS"
10174 root 16536 R /path/to/PROCESS1
10175 root 71720 S /path/to/PROCESS2
10177 root 27772 S sh -c /path/to/PROCESS3 10175
10076 root 11084 S /path/to/PROCESS3 100175

但我仍然不知道為什麼會這樣。有人可以建議在這種情況下發生了什麼樣的“魔法”嗎?

根據您的描述,這聽起來 PROCESS2 存在根本問題,導致它退出。如果我用 3 個程序對您所描述的內容進行建模,那麼當您將 3 個程序作為後台處理然後擷取並將第二個程序的 PID 傳遞給程序 3 時,它通常會像預期的那樣工作。

例子

範例腳本

$ cat runny.bash
#!/bin/bash

proc3func() {
 echo $1
 sleep 7 &
}

sleep 9 &
sleep 8 &
PID2=$!
proc3func ${PID2} &

範例執行

$ ./runny.bash ; sleep 2; ps -eaf
4279
UID        PID  PPID  C STIME TTY          TIME CMD
...
vagrant   4278     1  0 20:21 pts/1    00:00:00 sleep 9
vagrant   4279     1  0 20:21 pts/1    00:00:00 sleep 8
vagrant   4282     1  0 20:21 pts/1    00:00:00 sleep 7

在上面的輸出中,我們可以看到 PID,4279 被回顯到螢幕上,隨後的輸出ps -eaf顯示了我們的 3 個程序。

調試

我建議啟用set -x,以便您可以在執行腳本或像這樣執行它時遵循正在執行的命令:

$ bash -x ./runny.bash
+ PID2=4612
+ sleep 9
+ sleep 8
+ proc3func 4612
+ echo 4612
4612
+ sleep 7

引用自:https://unix.stackexchange.com/questions/462176