Vuelva a ejecutar continuamente un comando cuando termine en Bash

62

Estoy tratando de encontrar una manera simple de seguir ejecutando un comando cada vez que termina, por cualquier motivo (error u otro).

¿Cuál sería la mejor manera de abordar esto?

EDITAR: No estaba lo suficientemente claro antes. Necesito la próxima ejecución para esperar hasta que termine la anterior.

EDIT 2: Casi todas las respuestas funcionan muy bien. Pensé erróneamente que la mayoría de las respuestas bifurcarían el proceso o lo volverían a ejecutar solo una vez, ninguna de las cuales es deseada.


fuente
1
Aún no estás claro. Sería útil si mencionaras qué programa estás ejecutando.
Daniel Beck
1
-1 Esta pregunta no muestra ningún esfuerzo de investigación, ya que el usuario comentó que las respuestas no funcionaron en lugar de tratar de hacer lo que sugieren.
Daniel Beck

Respuestas:

39

Esto crea un bucle infinito, ejecutándose commanduna y otra vez.

while :
    do
        command
done
Dennis
fuente
Consulte la edición de la pregunta original. Necesito seguir ejecutándolo una y otra vez, no solo una vez.
8
@calcifer Esta respuesta funciona bastante bien. Hay algo inusual en su programa que ninguno de los cuatro usuarios que respondieron anticiparon hasta ahora y usted no lo mencionó.
Daniel Beck
@calcifer este es un bucle infinito. sigue repitiéndose hasta el final de los tiempos (bueno, hasta que el guión se termina de todos modos)
Nate Koppenhaver
1
Lo malo, pensé que esto (y todas las otras respuestas) bifurcará el proceso o lo volverá a ejecutar solo una vez, ninguno de los cuales es deseado. Entonces sí, esta respuesta funciona. Gracias.
1
una versión de línea: while true; do echo 'Hit CTRL+C'; sleep 1; donegracias a cyberciti.biz/faq/bash-infinite-loop~~V~~plural~~3rd
jk2K
107

El watchcomando repetirá un comando para siempre con un intervalo especificado:

watch -n0 <command>

Establecer -na cero efectivamente no pone el intervalo en nada (creo que es realmente .1 segundos).

watch También tiene los beneficios adicionales de alinear la salida para que los cambios visuales se puedan ver fácilmente, y tiene un interruptor para resaltar los cambios de la última ejecución.

Referencia: la página del manual del reloj :

watch ejecuta el comando repetidamente, mostrando su salida (la primera pantalla completa). Esto le permite ver el cambio de salida del programa con el tiempo. Por defecto, el programa se ejecuta cada 2 segundos; use -n o --interval para especificar un intervalo diferente.

El reloj funcionará hasta que se interrumpa.

Pablo
fuente
Consulte la edición de la pregunta original.
66
Todas las respuestas hasta ahora hacen esto, incluida esta. Linux no se bifurcará a menos que se lo pidas específicamente.
Paul
No sabía eso del tenedor, gracias.
No puedo ver ningún resultado con este método.
Raffi Khatchadourian
@RaffiKhatchadourian ¿Estás diciendo que si lo haces watch lsen un directorio que contiene archivos, no obtienes nada?
Paul
17

Una solución simple sería:

yourcommand; !#

;separa los comandos, permitiendo múltiples comandos en una línea ( Bash: Listas )

!#le dice a bash que "repita todo lo que he escrito hasta ahora en esta línea" ( Bash: Designadores de eventos )

Cielo azul
fuente
1
Lo siento, no fui lo suficientemente claro. Necesito seguir ejecutándolo una y otra vez, no solo una vez.
Gracias por esto, lo estaba buscando, especialmente porque en yourcommand; !!realidad no funciona con comandos en la misma línea, sin embargo, !#parece funcionar. ¡Salud!
sdaau
; !#no funcionó en ZSH, solo expande la declaración esencialmente clonándola, no la
activa
7

Puede planificar con anticipación durante la ejecución del comando (siempre que no sea interactivo) e ingresar !!cuál ejecutará el comando anterior nuevamente. Esto funciona, por ejemplo, durante ping -c 5.


También puede definir una función en bash:

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

Para persistir, guárdelo ~/.bashrc.

Entonces, puedes ejecutar tu comando así:

repeat ping -c5 heise.de

Si es un comando específico que desea ejecutar repetidamente (y no, por ejemplo, cualquier comando), puede reemplazar "$@"ese fragmento con su comando real y nombrar la función, por ejemplo, en su repeat_pinglugar.


Para que sea un bucle infinito, puedes hacer lo que @Dennis sugiere. Le recomiendo que agregue un período de espera si tiene la intención de usar esto en un shell interactivo, como este:

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

De lo contrario, es bastante inconveniente abortar este bucle infinito usando Ctrl-Z.

Daniel Beck
fuente
Consulte la edición de la pregunta original.
66
@calcifer Estas ejecuciones esperan hasta que vuelva la llamada del programa. ¿Su programa se separa del shell y regresa antes de que se cierre?
Daniel Beck
Lo malo, pensé que esto (y todas las otras respuestas) bifurcará el proceso o lo volverá a ejecutar solo una vez, ninguno de los cuales es deseado. Entonces sí, esta respuesta funciona. Gracias.
4

Dele a un whilebucle una condición booleana como la siguiente:

#!/bin/bash

while true; do

    do_something && wait

done

Esto se ejecutará una y otra vez hasta que bash reciba una señal para finalizar el proceso. Por lo general, en forma de ctrl+c.

También puede usar el watchcomando para ejecutar un script repetidamente también. Por ejemplo, un reloj simple en su terminal bash usando watchpodría verse así:

$ watch -t -n1 date +%T

La -topción le indica watchque no muestre un título del proceso que está ejecutando. Esto le da una salida limpia de solo el comando que se repite. La -n1opción le dice al reloj que se repita cada nsegundo. En este caso, -n1habrá intervalos de 1segundo. Luego el date +%Tcomando muestra la hora en el momento de la finalización del comando. Hacer este comando te dará un reloj activo en tu terminal.

Y luego, un método más que no está en ninguna de las otras respuestas sería una llamada a función infinita.

do_something() { do_something }; do_something && wait

Esto es esencialmente lo mismo que el whilebucle booleano que solo usa llamadas a funciones recursivas.

(editar) Para tener en cuenta los recursos de su máquina, he agregado el de && waitmodo que cada vez que se ejecuta un proceso, los bucles "esperarán" hasta que ese proceso finalice con el estado de salida 0 antes de la siguiente iteración. Esto es útil en un script de shell interactivo.


fuente
1
Hay un whileejemplo de bucle pero no está usando una truesintaxis booleana . Hay un watchejemplo, pero no ofrece muchas sintaxis útiles. Estoy exponiendo sobre estos para quien pueda ayudar. Quería darles una utilidad práctica a estos. El whilebucle booleano también puede ser falsey no ejecutarse hasta que se cumpla una condición falsa. Es bastante útil.
1
@ Spittin'IT Agregó un método que no se utiliza en otras respuestas para su conveniencia.
Es justo y entiendo ... ¡Solo estaba comentando mientras revisaba el módulo de revisión, pero fue una buena edición y seguimiento!
Pimp Juice IT
¿Cómo se ifsigue ejecutando de nuevo?
Kamil Maciorowski
Buen punto Kamil. Olvidé hacerlo recursivo jajaja. Se corrigió en la edición usando una función que se llamaba a sí misma en la ifdeclaración.
0

Este es otro método que uso para repetir un comando en bash. Esto puede sonar tonto para algunos, ya que no implica escribir un guión y puede ser conocido por muchos. Pero creo que vale la pena mencionarlo, ya que es rápido y amigable para principiantes, en el sentido de que no hay mucha sintaxis para recordar. Solo he probado esto en gnome-terminal de Ubuntu y es posible que otros terminales no lo admitan.

  1. Ingrese el comando en la terminal una vez.
  2. Seleccione el comando que incluye el carácter de nueva línea con el mouse.
  3. Copie la selección usando Ctrl-Insertar o usando el menú contextual (generalmente se accede con un clic derecho).
  4. Use Shift-Insert para pegar tantas veces como desee ejecutar el comando.

No tiene que esperar para pegar hasta que finalice cada comando. Los comandos pegados entran en una cola y se ejecutan uno tras otro.

jayadeepk
fuente
0

Me siento descarado hoy.

Leer de una de las corrientes infinitas y canalizarlo a xargs

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

Si necesita poner un poco de descanso allí, es probable que deba ejecutar sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
Jefferey Cave
fuente