我正在使用 Java exec 運行 bash 腳本,但是當我輸入 CTRL+C 時,Java 進程將退出,子進程也會退出,如何在 JVM 關閉后讓子進程繼續運行?String command = "ffmpeg -re -strict -2 -i video.mp4 -c:v copy -an -f rtp rtp://127.0.0.1:1234";Utils.writeToFile("sub.sh", command);new ProcessBuilder("parent.sh", "sub.sh").inheritIO() .start().waitFor();parent.sh:#!/bin/bashtrap '' SIGINT SIGTERM SIGQUIT SIGHUP SIGTSTPnohup "$@" &我已經在這里和這里閱讀了類似問題的答案,例如,在該腳本運行命令中使用 nohup 啟動父 bash 腳本,或使用 trap 命令來阻止信號,在我的研究中,它可以工作,例如“tail -f somefile”,但是不適用于我的用例“ffmpeg -params”,請幫忙,謝謝。
1 回答

MM們
TA貢獻1886條經驗 獲得超2個贊
長話短說
在你的中使用setsid
而不是:nohup
parent.sh
#!/bin/bash setsid $@ &
第一個問題是當您的 Java 程序接收到一個SIGTERM
信號時(在 之后CTRL + C
),JVM 向SIGKILL
子進程發送一個信號,該信號無法被捕獲、阻止或忽略。因此,一旦您的parent.sh
進程收到SIGKILL
,它就會被傳遞給它的子進程sub.sh
,從而停止該進程。
第二個問題是nohup "$@" &
你讓你的sub.sh
子程序在后臺運行,但它并沒有完全脫離當前終端。nohup
基本上是忽略信號SIGHUP
。它正常執行該過程(在后臺)并且實際上不提供守護進程。
nohup
您可以使用setsid代替,它通過創建一個新會話來分離子進程sub.sh
,然后該會話將沒有控制終端,因此不會接收到SIGKILL
信號。
執行此操作的另一種方法可能是使用disown
, like source $@ & disown
,但在這種情況下,它不會阻止parent.sh
正在運行的當前終端。問題是,您無法知道子進程何時完成。因此,您將有更多工作要做,以便監視子進程 ID。