Постоянно повторно выполнять команду, когда она заканчивается в Bash

62

Я пытаюсь найти простой способ повторного выполнения команды всякий раз, когда она завершается, по любой причине (ошибка или нет).

Каков наилучший способ приблизиться к этому?

РЕДАКТИРОВАТЬ: Я не был достаточно ясным, прежде чем. Мне нужно следующее выполнение, чтобы дождаться окончания предыдущего.

РЕДАКТИРОВАТЬ 2: почти все ответы работают отлично. Я ошибочно полагал, что большинство ответов либо разорвет процесс, либо повторно выполнит его только один раз, ни один из которых не требуется.


источник
1
Вы все еще не ясно. Было бы полезно, если бы вы упомянули, какую программу вы выполняете.
Даниэль Бек
1
-1 Этот вопрос не требует каких-либо исследований, так как пользователь отметил, что ответы не сработали, вместо того, чтобы фактически пытаться делать то, что они предлагают.
Даниэль Бек

Ответы:

39

Это создает бесконечный цикл, выполняемый commandснова и снова.

while :
    do
        command
done
Деннис
источник
Пожалуйста, смотрите редактирование исходного вопроса. Мне нужно продолжать выполнять его снова и снова, а не только один раз.
8
@calcifer Этот ответ работает довольно хорошо. В вашей программе есть что-то необычное, чего не ожидал ни один из четырех пользователей, отвечавших до сих пор, и вы не упомянули об этом.
Даниэль Бек
@ Calcifer это бесконечный цикл. это повторяется до конца времени (ну, пока сценарий не будет прекращен в любом случае)
Нейт Коппенхавер
1
Мое плохое, я думал, что это (и все другие ответы) либо раскрутит процесс, либо повторно выполнит его только один раз, ни один из которых не требуется. Так что да, этот ответ работает. Благодарю.
1
однострочная версия:, while true; do echo 'Hit CTRL+C'; sleep 1; doneспасибо cyberciti.biz/faq/bash-infinite-loop
jk2K
107

Команда watchбудет повторять команду всегда с указанным интервалом:

watch -n0 <command>

Установка -nна ноль эффективно ставит интервал в ничто (я думаю, что это действительно .1 секунды).

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

Ссылка: страница руководства часов :

Команда watch запускает команду несколько раз, отображая ее результат (первый экран). Это позволяет вам наблюдать за изменением выходных данных программы с течением времени. По умолчанию программа запускается каждые 2 секунды; используйте -n или --interval, чтобы указать другой интервал.

часы будут работать до тех пор, пока не прервутся.

Павел
источник
Пожалуйста, смотрите редактирование исходного вопроса.
6
Все ответы до сих пор делают это, включая этот. Linux не будет работать, если вы не попросите об этом.
Пол
Я не знал, что насчет вилки, спасибо.
Я не вижу никакого вывода, используя этот метод.
Раффи Хачадурян
@RaffiKhatchadourian Вы говорите, что если вы делаете watch lsв каталоге, содержащем файлы, вы ничего не получаете?
Пол
17

Простое решение будет:

yourcommand; !#

;разделяет команды, позволяя использовать несколько команд в одной строке ( Bash: Lists )

!#говорит bash «повторить все, что я написал до сих пор в этой строке» ( Bash: Event-Designators )

Синее небо
источник
1
Извините, я не достаточно ясно Мне нужно продолжать выполнять его снова и снова, а не только один раз.
Спасибо за это, я искал это, тем более yourcommand; !!что фактически не работает с командами в одной строке, однако, !#похоже, работает. Ура!
sdaau
; !#не работал на ZSH, он просто расширяет утверждение, по сути клонируя его, он не вызывает его
revelt
7

Вы можете планировать заранее во время выполнения команды (при условии, что она не является интерактивной) и ввести, !!которая снова выполнит предыдущую команду. Это работает, например, во время ping -c 5.


Вы также можете определить функцию в bash:

function repeat { "$@"; "$@"; }

Чтобы сохранить это, сохраните это в ~/.bashrc.

Затем вы можете запустить свою команду следующим образом:

repeat ping -c5 heise.de

Если это определенная команда, которую вы хотите выполнить многократно (а не, например, какая-либо команда), вы можете заменить "$@"в этом фрагменте вашу фактическую команду и назвать функцию, например, repeat_pingвместо этого.


Чтобы сделать его бесконечным циклом, вы можете делать то, что предлагает @Dennis. Я рекомендую вам добавить период ожидания, если вы собираетесь использовать это в интерактивной оболочке, например:

function repeat { while 1 ; do "$@" ; sleep 1 ; done; }

В противном случае довольно неудобно прерывать использование этого бесконечного цикла Ctrl-Z.

Даниэль Бек
источник
Пожалуйста, смотрите редактирование исходного вопроса.
6
@calcifer Эти выполнения ждут, пока не вернется вызов программы. Отключается ли ваша программа от оболочки и возвращается до ее завершения?
Даниэль Бек
Мое плохое, я думал, что это (и все другие ответы) либо раскрутит процесс, либо повторно выполнит его только один раз, ни один из которых не требуется. Так что да, этот ответ работает. Благодарю.
4

Дайте whileциклу логическое условие, такое как:

#!/bin/bash

while true; do

    do_something && wait

done

Это будет выполняться снова и снова, пока bash не получит сигнал о завершении процесса. Обычно в форме ctrl+c.

Вы также можете использовать watchкоманду для многократного запуска скрипта. Например, простые часы в вашем терминале bash watchмогут выглядеть так:

$ watch -t -n1 date +%T

-tОпция указывает , watchчтобы не отображать название процесса он работает. Это дает вам чистый вывод только повторяемой команды. -n1Опция говорит смотреть повторять каждые nсекунды. В этом случае -n1будут интервалы 1секунды. Затем date +%Tкоманда показывает время во время выполнения команды. Выполнение этой команды даст вам активные часы в вашем терминале.

И тогда еще один метод, которого нет ни в одном из других ответов, - это бесконечный вызов функции.

do_something() { do_something }; do_something && wait

По сути, это то же самое, что и логический whileцикл, использующий только рекурсивные вызовы функций.

(edit) Для того, чтобы помнить о ресурсах вашей машины, я добавил && waitтак, что при каждом запуске процесса циклы будут «ждать», пока этот процесс не завершится со статусом выхода 0 до следующей итерации. Это полезно в интерактивном скрипте оболочки.


источник
1
Есть whileпример цикла, но он не использует логический trueсинтаксис. Есть watchпример, но он не дает много полезного синтаксиса. Я излагаю их, кому бы это ни помогло. Я хотел дать некоторую практическую полезность этим. whileЛогический цикл также может быть falseи не выполнять , пока не соответствует действительности условие не будет выполнено. Это довольно удобно.
1
@ Spittin'IT Добавлен метод, который не используется в других ответах для вашего удобства.
Достаточно справедливо, и я понимаю ... Я просто комментировал, когда прошел через модуль обзора, но приятно редактировать и следить !!
Сок Pimp IT
Как ifпродолжать повторное выполнение?
Камиль Мачоровский
Хороший вопрос, Камил. Забыл сделать это рекурсивным лол. Исправлено при редактировании с использованием функции, вызывающей себя в ifвыражении.
0

Это еще один метод, который я использую, чтобы повторить команду в bash. Для некоторых это может показаться глупым, поскольку не требует написания сценария и может быть известно многим. Но я думаю, что стоит упомянуть, так как он быстрый и удобный для начинающих, в том смысле, что синтаксис запоминать не так много. Я проверял это только в gnome-терминале Ubuntu, и другие терминалы могут не поддерживать это.

  1. Введите команду в терминале один раз.
  2. Выберите команду, включая символ новой строки, с помощью мыши.
  3. Скопируйте выделение с помощью Ctrl-Insert или с помощью контекстного меню (обычно доступ с помощью правой кнопки мыши).
  4. Используйте Shift-Insert, чтобы вставить столько раз, сколько вы хотите выполнить команду.

Вам не нужно ждать вставки, пока не завершится каждая команда. Вставленные команды попадают в очередь и выполняются одна за другой.

jayadeepk
источник
0

Я чувствую себя дерзким сегодня.

Прочитайте один из бесконечных потоков и отправьте xargs

cat /dev/zero | xargs --null echo hello there

Если вам нужно сделать небольшой перерыв, вам, скорее всего, придется выполнить sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
Джеффри Кейв
источник