在運行進程中按 Ctrl+C 後,透過腳本開啟的 Shell 標籤掛起

在運行進程中按 Ctrl+C 後,透過腳本開啟的 Shell 標籤掛起

我有以下腳本:

#!/usr/bin/env zsh
START_FOREMAN='/usr/bin/zsh -c "source /home/user/.zshrc; foreman start" zsh'
xfce4-terminal --tab -H -T app-server --working-directory=/home/user/git/app -e $START_FOREMAN

xfce4-terminal --tab -H -T api-server --working-directory=/home/user/git/api -e $START_FOREMAN

這兩個命令都取決於環境設定(chruby配置),所以我./zshrc在運行之前獲取我的文件foreman寶石。

但是,如果我運行此命令,然後嘗試Ctrl+C退出長時間運行的進程 - shell 會結束,並且我永遠不會得到提示。

注意:在同一目錄中的新 shell 中執行 foreman start 後會傳回提示符號給我Ctrl+C

編輯:人們似乎對工頭的問題感到困擾,但我認為情況並非如此,因為這與運行./gradlew bootRun或任何長時間運行的進程有關。

工頭肯定退出:

^CSIGINT received
16:13:09 system       | sending SIGTERM to all processes
16:13:10 api.1 | exited with code 130

與 Spring boot 一樣:

java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:291)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at org.gradle.process.internal.streams.ExecOutputHandleRunner.run(ExecOutputHandleRunner.java:51)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
:bootRun FAILED
> Building 100%

此時我無能為力 - 一切都被忽略,我必須關閉選項卡。

答案1

您觀察到的是兩件事的組合:

  1. Ctrl-C 將 INT 傳送到進程組,這表示不僅是您長時間運行的進程,還包括桀騁它正在運行的進程將同時終止(並且它不會有機會重新啟動)。

  2. xfce4-terminal,由於 -H 標誌,在進程結束後不會關閉選項卡:

-H, --hold 使終端在子命令終止後保持不變

這使得它看起來像是懸掛著的

最簡單的測試案例可能如下所示:

CMD=xeyes
START=$'/usr/bin/zsh -c \''$CMD$'; /usr/bin/zsh\''
xfce4-terminal --tab -H -T mycommand --working-directory=$HOME -e "$START"

如果您啟動此功能,「xeyes」將跟隨您,直到您按下Ctrl+C,此時它們將關閉,並且您的終端將顯示為掛起。

但如果不是點擊Ctrl+C你只需殺死 xeyes 本身(即使用 xkill 或視窗管理器工作列),桀騁會話將按預期開始。

解決此問題的方法是攔截 SIGINT 並重新啟動 shell,如下所示:

CMD=xeyes
START=$'/usr/bin/zsh -c \'trap "exec /usr/bin/zsh" INT;'$CMD$'; exec /usr/bin/zsh\''
xfce4-terminal --tab -H -T mycommand --working-directory=$HOME -e "$START"

請注意,您可能還需要刪除“-H”,以便在退出 shell 時關閉選項卡。

相關內容