Execute continuamente um comando quando ele terminar no Bash

62

Estou tentando descobrir uma maneira simples de continuar reexecutando um comando sempre que ele for concluído, por qualquer motivo (erro ou não).

Qual seria a melhor maneira de abordar isso?

Edição: Eu não estava claro o suficiente antes. Preciso que a próxima execução aguarde até a anterior terminar.

EDIT 2: Quase todas as respostas funcionam muito bem. Eu pensei erroneamente que a maioria das respostas iria bifurcar o processo ou executá-lo apenas uma vez, nenhuma das quais é desejada.


fonte
11
Você ainda não está claro. Ajudaria se você mencionasse o programa que está executando.
Daniel Beck
11
-1 Esta pergunta não mostra nenhum esforço de pesquisa, pois o usuário comentou que as respostas não funcionaram, em vez de realmente tentar fazer o que elas sugerem.
Daniel Beck

Respostas:

39

Isso cria um loop infinito, executando commandrepetidamente.

while :
    do
        command
done
Dennis
fonte
Consulte a edição da pergunta original. Eu preciso continuar re-executando repetidamente, não apenas uma vez.
8
@calcifer Esta resposta funciona muito bem. Há algo incomum em seu programa que nenhum dos quatro usuários que responderam até agora antecipou e você não mencionou.
Daniel Beck
@calcifer este é um loop infinito. continua repetindo até o fim dos tempos (bem, até que o script é encerrado de qualquer maneira)
Nate Koppenhaver
11
Meu mal, pensei que isso (e todas as outras respostas) ou bifurcariam o processo ou o executariam novamente apenas uma vez, nenhum dos quais é desejado. Então, sim, esta resposta funciona. Obrigado.
11
uma versão de linha: while true; do echo 'Hit CTRL+C'; sleep 1; donegraças a cyberciti.biz/faq/bash-infinite-loop
jk2K
107

O watchcomando repetirá um comando para sempre com um intervalo especificado:

watch -n0 <command>

Definir -nzero efetivamente coloca o intervalo em nada (acho que são realmente 0,1 segundos).

watch também possui os benefícios adicionais de alinhar a saída para que as alterações visuais possam ser vistas facilmente e possui uma opção para destacar as alterações da última execução.

Referência: a página do manual do relógio :

O watch executa o comando repetidamente, exibindo sua saída (a primeira tela cheia). Isso permite que você assista a saída do programa mudar ao longo do tempo. Por padrão, o programa é executado a cada 2 segundos; use -n ou --interval para especificar um intervalo diferente.

o relógio funcionará até ser interrompido.

Paulo
fonte
Consulte a edição da pergunta original.
6
Todas as respostas até agora fazem isso, incluindo esta. O Linux não será bifurcado, a menos que você solicite especificamente.
Paul
Eu não sabia disso sobre garfo, obrigado.
Não consigo ver nenhuma saída usando esse método.
Raffi Khatchadourian 8/03/16
@RaffiKhatchadourian Você está dizendo que se estiver watch lsem um diretório que contém arquivos, não recebe nada?
Paulo Paul
17

Uma solução simples seria:

yourcommand; !#

;separa comandos, permitindo vários comandos em uma linha ( Bash: Lists )

!#diz ao bash para "repetir tudo o que escrevi até agora nesta linha" ( Bash: Designadores de Eventos )

Céu azul
fonte
11
Desculpe, eu não estava claro o suficiente. Eu preciso continuar re-executando repetidamente, não apenas uma vez.
Obrigado por isso, eu estava procurando, especialmente porque yourcommand; !!, na verdade, não funciona com comandos na mesma linha, !#parece funcionar. Felicidades!
Sdaau
; !#não funcionou no ZSH, apenas expande a declaração essencialmente cloná-lo, não provocá-lo
revelt
7

Você pode planejar com antecedência durante a execução do comando (desde que não seja interativo) e inserir o !!que executará o comando anterior novamente. Isso funciona, por exemplo, durante ping -c 5.


Você também pode definir uma função em bash:

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

Para persistir, armazene-o ~/.bashrc.

Em seguida, você pode executar seu comando assim:

repeat ping -c5 heise.de

Se é um comando específico que você deseja executar repetidamente (e não, por exemplo, qualquer comando), você pode substituir "$@"esse trecho pelo seu comando real e nomear a função, por exemplo repeat_ping.


Para torná-lo um loop infinito, você pode fazer o que @Dennis sugere. Eu recomendo que você adicione um período de espera se você pretende usá-lo em um shell interativo, como este:

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

Caso contrário, é bastante inconveniente abortar esse loop infinito usando Ctrl-Z.

Daniel Beck
fonte
Consulte a edição da pergunta original.
6
@calcifer Essas execuções esperam até a chamada do programa retornar. Seu programa se desconecta do shell e retorna antes de sair?
Daniel Beck
Meu mal, pensei que isso (e todas as outras respostas) ou bifurcariam o processo ou o executariam novamente apenas uma vez, nenhum dos quais é desejado. Então, sim, esta resposta funciona. Obrigado.
4

Dê a um whileloop uma condição booleana, como a seguir:

#!/bin/bash

while true; do

    do_something && wait

done

Isso será executado repetidamente até que o bash receba um sinal para finalizar o processo. Geralmente na forma de ctrl+c.

Você também pode usar o watchcomando para executar um script repetidamente também. Por exemplo, um relógio simples no seu terminal bash usando watchpode se parecer com:

$ watch -t -n1 date +%T

A -topção informa watchpara não exibir um título do processo que está sendo executado. Isso fornece uma saída limpa apenas do comando que está sendo repetido. A -n1opção informa ao relógio para repetir a cada nsegundo. Nesse caso, -n1haverá intervalos de 1segundo. Em seguida, o date +%Tcomando mostra a hora no momento da conclusão do comando. Ao executar este comando, você terá um relógio ativo no seu terminal.

E então mais um método que não está em nenhuma das outras respostas seria uma chamada de função infinita.

do_something() { do_something }; do_something && wait

É essencialmente o mesmo que o whileloop booleano, usando apenas chamadas de função recursivas.

(edit) Para manter os recursos da sua máquina em mente, eu adicionei o && waitpara que, sempre que um processo for executado, os loops "aguardem" até que o processo termine com o status de saída 0 antes da próxima iteração. Isso é útil em um script de shell interativo.


fonte
11
Há um whileexemplo de loop, mas ele não está usando uma truesintaxe booleana . Há um watchexemplo, mas ele não fornece muitas sintaxes úteis. Estou explicando isso para quem puder ajudar. Eu queria dar alguma utilidade prática a eles. O whileloop booleano também pode ser falsee não ser executado até que uma condição falsa seja atendida. É bastante útil.
11
@ Spittin'IT Adicionado um método que não é usado em outras respostas para sua conveniência.
É justo o suficiente e eu entendo ... Eu estava apenas comentando enquanto eu passava pelo módulo de revisão, mas era bom editar e acompanhar !!
Pimp Juice IT
Como ifcontinuar reexecutando?
Kamil Maciorowski
Bom ponto Kamil. Esqueceu de torná-lo lol recursivo. Corrigido na edição usando uma função que se chama na ifinstrução.
0

Este é outro método que eu uso para repetir um comando no bash. Para alguns, isso pode parecer bobo, pois não envolve escrever um script e pode ser conhecido por muitos. Mas acho que vale a pena mencionar, pois é rápido e fácil para iniciantes, no sentido de que não há muita sintaxe para lembrar. Eu só testei isso no gnome-terminal do Ubuntu e outros terminais podem não suportar isso.

  1. Digite o comando no terminal uma vez.
  2. Selecione o comando incluindo o caractere de nova linha com o mouse.
  3. Copie a seleção usando Ctrl-Insert ou usando o menu de contexto (geralmente acessado com o botão direito).
  4. Use Shift-Insert para colar quantas vezes desejar para executar o comando.

Você não precisa esperar para colar até que cada comando termine. Os comandos colados entram em uma fila e são executados um após o outro.

jayadeepk
fonte
0

Estou me sentindo mal hoje.

Leia de um dos fluxos infinitos e canalize-o para xargs

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

Se você precisar fazer uma pequena pausa, provavelmente precisará executar sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
Caverna de Jefferey
fonte