Завершение бесконечного цикла

bash(1) страница справочника, раздел EXPANSION, подраздел Замены Команды:

   Command substitution allows the output of a command to replace the com-
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com-
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

Кавычки то, потому что [ почти так же умно как шлакоблок и не любит пустых строк.

54
05.07.2012, 02:24
10 ответов

Проверьте статус выхода команды. Если команда была завершена сигналом, код выхода будет 128 + число сигнала. Из онлайн-документации GNU для удара:

В целях оболочки успешно выполнилась команда, которая выходит с нулевым статусом выхода. Ненулевой статус выхода указывает на отказ. Эта на вид парадоксальная схема используется, таким образом, существует один четко определенный способ указать на успех и множество способов указать на различные виды отказа. Когда команда завершается на фатальном сигнале, число которого является N, Bash использует значение 128+N в качестве статуса выхода.

POSIX также указывает, что значение команды, которая завершенный сигналом больше, чем 128, но, кажется, не указывает, что его точное значение как GNU делает:

О статусе выхода команды, которая завершилась, потому что он получил сигнал, нужно сообщить как больше, чем 128.

Например, при прерывании команды Ctrl-C, код выхода будет 130, потому что SIGINT является сигналом 2 в системах Unix. Так:

while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
39
27.01.2020, 19:33
  • 1
    Нужно упомянуть, что это не гарантируется, на самом деле, много приложений не сделают этого. –  Chris Down 04.07.2012, 04:18
  • 2
    @Kyle Jones: можно ли связаться с POSIX / документы GNU то упоминание это? кавычки –  Ciro Santilli 新疆改造中心法轮功六四事件 15.03.2014, 22:03
  • 3
    @cirosantilli Сделан. –  Kyle Jones 16.03.2014, 00:44
  • 4
    @KyleJones, Спасибо! Все еще на практике не работающий на КОМАНДУ = paplay alert.ogg, возможно, потому что paplay обрабатывает сигнал? –  Ciro Santilli 新疆改造中心法轮功六四事件 16.03.2014, 08:49
  • 5
    @cirosantilli Да, это - причина. Если процесс обрабатывает сигнал и выходы, это отличается, чем процесс, завершаемый необработанным сигналом. –  Kyle Jones 16.03.2014, 09:21

Я сказал бы, что могло бы быть лучше поместить Ваш бесконечный цикл в сценарий и сигналы дескриптора там. Вот основная начальная точка. Я уверен, что Вы захотите изменить его для удовлетворения. Использование сценария trap поймать ctrl-c (или SIGTERM), избавляется от команды (я использовал sleep здесь как тест) и выходы.

cleanup ()
{
kill -s SIGTERM $!
exit 0
}

trap cleanup SIGINT SIGTERM

while [ 1 ]
do
    sleep 60 &
    wait $!
done
20
27.01.2020, 19:33
  • 1
    Хороший. Вот то, как я использовал эту подсказку для создания авторестарта netcat оберткой: trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done –  Douglas 13.01.2013, 15:00
  • 2
    , если Вы добавляете это trap приблизьтесь к тому же (удар) к сценарию с бесконечным циклом, который будет уничтожен, используйте $$ вместо $! (см. здесь), –  ardnew 22.05.2017, 23:37

Я обычно просто удерживаю Ctrl-C. Рано или поздно это зарегистрируется между COMMANDи таким образом оконечный while цикл. Возможно, существует лучший путь.

15
27.01.2020, 19:33
  • 1
    Не уверенный, почему, но это перестало работать для определенных КОМАНД как paplay на 1 файле с. –  Ciro Santilli 新疆改造中心法轮功六四事件 15.03.2014, 13:07
  • 2
    Это работало на меня –  alexandr 28.05.2015, 13:56

Если Вы выполняете удар с -e это выйдет на любых состояниях ошибки:

#!/bin/bash -e
false # returns 1
echo This won't be printed
8
27.01.2020, 19:33
  1. Можно всегда уничтожать процесс с помощью его PID, нет никакой потребности закрыть терминал
  2. Если Вы хотите выполнить что-то в бесконечном цикле как демон затем, Вы лучше всего поместили его в фоновом режиме
  3. while : создаст бесконечный цикл и сохраняет Вас пишущий [ 1 ]

    while :; do COMMAND; done &
    

Это распечатает PID. Если Вы выходите из своего быстрого использования ctrl+d затем фоновое задание не выйдет, и можно позже уничтожить задание отовсюду с помощью kill PID

Если Вы теряете след своего PID, можно использовать pstree -pa $USER или pgrep -fl '.*PROCESS.*' помочь Вам найти его

2
27.01.2020, 19:33
[117247]Вы можете остановиться и поставить свое задание в фоновом режиме во время работы, используя [117597]ctrl[117598]+[117599]z[117600]. Затем Вы можете убить свою работу с помощью:

Где [1] - номер Вашей работы.[117250].

49
27.01.2020, 19:33

Почему не просто,

while [ 1 ]; do COMMAND || break; done;

Или при использовании в сценарии

#!/bin/bash
while [ 1 ]; do
  # ctrl+c terminates COMMAND and exits the while loop
  # (assuming COMMAND responds to ctrl+c)
  COMMAND || break
done;
10
27.01.2020, 19:33

Я предпочитаю другое решение:

touch.runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done

Чтобы закрыть цикл, просто выполните:

rm.runcmd && kill `pidof COMMAND`
3
27.01.2020, 19:33

Используйтеtrap-

exit_()
{
    exit
}

while true
do
    echo 'running..'
    trap exit_ int
done
0
27.01.2020, 19:33

Мне достаточно хорошо помогает:

while sleep 1; do COMMAND; done

Это работает, потому что sleep 1 какое-то время задерживается, и если он получает Ctrl + C, он возвращается с ненулевым значением, и цикл завершается.

3
04.03.2020, 13:40

Теги

Похожие вопросы