У меня есть простой скрипт bash, который запускает два сервера:
#!/bin/bash
(cd ./frontend && gulp serve) & (cd ./backend && gulp serve --verbose)
Если вторая команда завершается, кажется, что первая команда продолжает выполняться.
Как я могу изменить это так, что если одна из команд завершается, другая завершается?
Обратите внимание, что нам не нужно проверять уровни ошибок фоновых процессов, просто они вышли.
bash
shell-script
background-process
blah238
источник
источник
gulp ./fronend/serve && gulp ./backend/serve --verbose
?serve
это аргумент, а не файл, поэтому необходимо установить текущий каталог.Ответы:
Это запускает оба процесса, ждет первого, который завершает, а затем убивает другой:
Как это устроено
Начало:
Две вышеупомянутые команды запускают оба процесса в фоновом режиме.
Подождите
Это ожидает завершения любого фонового задания.
Из-за
-n
опции, это требует bash 4.3 или лучше.Убийство
Это убивает любую работу, для которой текущий процесс является родительским. Другими словами, это убивает любой фоновый процесс, который все еще выполняется.
Если вашей системы нет
pkill
, попробуйте заменить эту строку на:что также убивает текущую группу процессов .
Легко тестируемый пример
Изменяя скрипт, мы можем протестировать его даже без
gulp
установленного:Вышеприведенный скрипт может быть запущен как
bash script.sh 1 3
и первый процесс завершается первым. В качестве альтернативы, можно запустить его как,bash script.sh 3 1
и второй процесс завершится первым. В любом случае можно увидеть, что это работает как хотелось бы.источник
bash
поддерживают-n
опцию дляwait
команды. (2) Я согласен на 100% с первым предложением - ваше решение запускает два процесса, ожидает завершения первого и затем убивает другое. Но вопрос гласит: «… если одна из команд выдает ошибку , другая завершается?» Я считаю, что ваше решение не то, что хочет ОП. (3) Почему вы перешли(…) &
на{ …; } &
? В&
силах списка (группа команд) , чтобы запустить в субоболочке в любом случае. ИМХО, вы добавили персонажей и, возможно, привели в замешательство (мне пришлось дважды взглянуть на это, чтобы понять это) без пользы.pkill
не доступен для меня, но,kill 0
кажется, имеет тот же эффект. Также я обновил свою среду Git для Windows, иwait -n
теперь она выглядит так, как будто работает, поэтому я принимаю этот ответ.kill
. документация по моей системе не упоминает об этом. Тем не менее,kill 0
работает в любом случае. Хорошая находка!Это сложно. Вот что я разработал; может быть возможно упростить / упростить это:
while true; do sleep 42; done &
), который спит / делает паузу навсегда. Если вы уверены, что две ваши команды прекратят работу в течение определенного времени (например, часа), вы можете изменить это на один сон, который будет превышать этот (например,sleep 3600
). Затем вы можете изменить следующую логику, чтобы использовать ее как тайм-аут; то есть, убить процессы, если они все еще работают после того времени. (Обратите внимание, что вышеприведенный скрипт в настоящее время этого не делает.)./
дляcd
.command & echo "$!" > somewhere; wait "$!"
сложная конструкция, которая запускает процесс асинхронно, захватывает его PID, а затем ждет его; делая это своего рода передним (синхронным) процессом. Но это происходит в(…)
списке, который полностью находится в фоновом режиме, поэтомуgulp
процессы выполняются асинхронно.gulp
процессов запишите его состояние во временный файл и завершите процесс «навсегда спать».sleep 1
для защиты от состояния гонки, когда первый фоновый процесс умирает до того, как второй получит возможность записать свой PID в файл.gulp
процессов, как указано выше.источник
Для полноты вот что я в итоге использовал:
Это работает для меня на Git для Windows 2.5.3 64-bit. Старые версии могут не принять
-n
опцию наwait
.источник
В моей системе (Centos)
wait
нет,-n
поэтому я сделал это:Это не ждет «либо», а ждет первого. Но все же это может помочь, если вы знаете, какой сервер будет остановлен первым.
источник
wait
имеет-n
опцию или нет , зависит от используемой оболочки, а не распределение Linux.