Вкладка оболочки, открытая через скрипт, зависает после нажатия Ctrl+C в запущенном процессе

Вкладка оболочки, открытая через скрипт, зависает после нажатия Ctrl+C в запущенном процессе

У меня есть следующий скрипт:

#!/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выйти из долго выполняющегося процесса, оболочка завершится, и я больше не получу приглашение.

Примечание: запуск 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+С, после чего они закроются, а ваш терминал будет выглядеть зависшим.

Но если вместо того, чтобы нажатьCtrl+Свы просто убьете сами xeyes (т.е. с помощью xkill или панели задач оконного менеджера),зшсеанс начнется, как и предполагалось.

Обойти эту проблему можно, перехватив SIGINT и перезапустив оболочку, например так:

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», чтобы вкладка закрывалась при выходе из оболочки.

Связанный контент