Há um comando interno do Unix, repeat
cujo primeiro argumento é o número de vezes para repetir um comando, em que o comando (com qualquer argumento) é especificado pelos argumentos restantes para repeat
.
Por exemplo,
% repeat 100 echo "I will not automate this punishment."
ecoará a sequência especificada 100 vezes e depois parará.
Eu gostaria de um comando semelhante - vamos chamá-lo forever
- que funciona da mesma forma, exceto que o primeiro argumento é o número de segundos para pausar entre repetições e repete para sempre. Por exemplo,
% forever 5 echo "This will get echoed every 5 seconds forever and ever."
Pensei em perguntar se existe algo assim antes de escrevê-lo. Eu sei que é como um script Perl ou Python de 2 linhas, mas talvez haja uma maneira mais padrão de fazer isso. Caso contrário, fique à vontade para publicar uma solução em sua linguagem de script favorita, estilo Rosetta Stone .
PS: Talvez uma maneira melhor de fazer isso seja generalizar repeat
para levar o número de vezes a repetir (com -1 significa infinito) e o número de segundos para dormir entre as repetições. Os exemplos acima se tornariam:
% repeat 100 0 echo "I will not automate this punishment."
% repeat -1 5 echo "This will get echoed every 5 seconds forever."
fonte
type repeat
e me avise de onde vem?repeat
é um comando interno no csh e no tcsh.Respostas:
Experimente o
watch
comandoDe modo a:
executará o comando a cada segundo (bem, tecnicamente, a cada segundo mais o tempo necessário para
command
executar comowatch
(pelo menos as implementaçõesprocps
ebusybox
) apenas dorme um segundo entre duas execuções decommand
), para sempre.Deseja passar o comando para, em
exec
vez desh -c
, use a-x
opção:No macOS, você pode obter
watch
das portas Mac :Ou você pode obtê-lo no Homebrew :
fonte
while true; do X; sleep Y; done
- isso é muito melhor.cmdwatch
no FreeBSD (a partir das portas :)sysutils/cmdwatch
.Bater
while
+sleep
:Aqui está a mesma coisa que uma linha de taquigrafia (dos comentários abaixo):
Usa
;
para separar comandos e usossleep 1
para owhile
teste, pois sempre retorna true. Você pode colocar mais comandos no loop - basta separá-los com;
fonte
sleep
nem sempre retorna verdadeiro. Ī̲ usei esses loops (embora com um atraso maior), ou seja, porque existe uma maneira de finalizá-lo normalmente com a interrupção do processo de suspensão.Esta é apenas uma versão mais curta de outras
while+sleep
respostas, se você estiver executando esse tipo de tarefa frequentemente como sua rotina diária, usar isso poupará o pressionamento desnecessário de teclas e se sua linha de comando começar a entender mais, será mais fácil. Mas este começa com o sono primeiro.Isso geralmente é útil se você precisar seguir algo com saída em uma linha, como carga da máquina:
fonte
while clear; do date; command;sleep 5; done
while sleep
combinação, economiza keytokes!Um problema que todas as respostas postadas até agora têm é que o tempo em que o comando é executado pode ser desviado. Por exemplo, se você
sleep 10
executar um comando entre, e o comando demorar 2 segundos para ser executado, será executado a cada 12 segundos; se leva um tempo variável para ser executado, a longo prazo, o tempo em que é executado pode ser imprevisível.Isso pode ser exatamente o que você deseja; Nesse caso, use uma das outras soluções ou use essa, mas simplifique a
sleep
chamada.Para resolução de um minuto, os trabalhos cron serão executados no horário especificado, independentemente do tempo que cada comando leve. (De fato, um novo trabalho cron será iniciado, mesmo que o anterior ainda esteja em execução.)
Aqui está um script Perl simples que dorme até o próximo intervalo. Por exemplo, com um intervalo de 10 segundos, o comando pode ser executado às 12:34:00, 12:34:10, 12:34:20, etc., mesmo se o o próprio comando leva vários segundos. Se o comando for executado por mais de
interval
segundos, o próximo intervalo será ignorado (diferente do cron). O intervalo é calculado em relação à época, portanto, um intervalo de 86400 segundos (1 dia) será executado à meia-noite UTC.fonte
while :; do sleep 1m & command; wait; done
wait
esperará por todos eles). Isso é corrigível mudandowait
parawait $!
, onde$!
está o PID dosleep
processo. Poste isso como uma resposta e eu vou votar novamente. Mas produz alguma saída estranha em um shell interativo.Acho que todas as respostas aqui até agora são muito complicadas ou, em vez disso, respondem a uma pergunta diferente:
A verdadeira questão era:
Essas são duas coisas muito diferentes quando o comando leva algum tempo para terminar.
Tomemos, por exemplo, o script
foo.sh
(finja que este é um programa que leva alguns segundos para ser concluído).Você deseja executar isso a cada segundo, e a maioria sugere
watch -n1 ./foo.sh
, ouwhile sleep 1; do ./foo.sh; done
. No entanto, isso fornece a saída:O que não é exatamente executado a cada segundo. Mesmo com a
-p
bandeira, como aman watch
página sugere, isso pode resolver o resultado.Uma maneira fácil de realizar a tarefa desejada, na qual alguns tocam, é executar o comando em segundo plano. Em outras palavras:
E isso é tudo o que existe.
Você pode executá-lo a cada 500 ms com
sleep 0.5
o que você tem.fonte
while :; do sleep 1 & ./foo.sh; wait; done
date +"%H:%M:%S.%N"
em foo.sh para ver como a fração aumentará lentamente em cada loop.Em
bash
:(
echo
pode ser substituído por qualquer comando ...Ou em
perl
:Onde
print "I will not automate this punishment in absurdum.\n"
poderia ser substituído por "qualquer" comando cercado por reticulares (`).E, para uma pausa, adicione uma
sleep
instrução dentro do loop for:e
fonte
while [ 0 ]
é uma maneira ruim de escrever. Isso significa que0
é uma string com comprimento> 0while [ 1 ]
ouwhile [ jeff ]
faria a mesma coisa. Melhor escreverwhile true
.while :
Recent bash> = 4.2 no kernel recente do Linux, com base em respostas.
Para limitar o tempo de execução, não há garfos ! Somente interno é usado.
Para isso, eu uso a
read
função embutida em vez desleep
. Unfortunely isso não vai funcionar com Notty sessões.Função bash rápida "
repeat
" conforme solicitado:Pouco teste com seqüências de caracteres citadas:
Dependendo da granularidade e duração do comando enviado ...
Nos kernels recentes do Linux, há um arquivo
/proc/timer_list
contendo informações de tempo em nanossegundos.Se você deseja executar um comando exatamente uma vez por segundo, seu comando deve terminar em menos de um segundo! E a partir daí, você precisa
sleep
apenas o restante do segundo atual.Se o atraso for mais importante e seu comando não exigir um tempo significativo, você poderá:
Mas se seu objetivo é obter granularidade mais fina, você deve:
Use as informações em nanossegundos para esperar até o início de um segundo ...
Para isso, escrevi uma pequena função bash:
Depois de adquiri-los, você pode:
executar
${command[@]}
diretamente na linha de comando, do que comparar comisso deve dar exatamente o mesmo resultado.
Contrata a função bash "
repeat
" conforme solicitado:Você pode obter isso:
Então tente:
fonte
read -t
é um built-in , enquantosleep
não é. Isto pode ter efeito fronteira (ou seja, atingir [chave: retorno] interromper calmamente o sono ), mas esta poderia ser tratada por meio de testes$foo
Gostaria de experimentar isso (Bash)?
fonte
repeat
é específico para csh e tcsh.Perl
fonte
O Bash e algumas de suas conchas semelhantes têm a
(( ... ))
notação conveniente em que expressões aritméticas podem ser avaliadas.Portanto, como resposta ao seu terceiro desafio, em que a contagem de repetições e o atraso entre cada repetição devem ser configuráveis, aqui está uma maneira de fazer isso:
Essa resposta também sofre com o desvio de tempo coberto na resposta de Keith .
fonte
Conforme mencionado por gbrandt, se o
watch
comando estiver disponível, use-o definitivamente. Alguns sistemas Unix, no entanto, não o instalam por padrão (pelo menos não onde eu trabalho).Aqui está outra solução com sintaxe e saída ligeiramente diferentes (funciona em BASH e SH):
Editar: removi alguns "." na última declaração de eco ... ressaca dos meus dias Perl;)
fonte
while [ 1 ]
só funciona porque 1 é tratado como uma string, assim comowhile [ -n 1 ]
.while [ 0 ]
ouwhile [ jeff ]
faria a mesma coisa.while true
faz muito mais sentido.Se sua intenção não é exibir uma mensagem na tela e se você puder repetir o trabalho em minutos, o crontab talvez seja sua melhor ferramenta. Por exemplo, se você deseja executar seu comando a cada minuto, escreva algo como isto em seu
crontab
arquivo:Confira o tutorial para mais exemplos. Além disso, você pode definir os horários facilmente usando o Crontab Code Generator .
fonte
E se tivéssemos os dois?
Aqui está a idéia: com apenas "intervalo", ele se repete para sempre. Com "intervalo" e "tempos", repete esse número de vezes, separado por "intervalo".
O uso :
Então, o algoritmo será:
Portanto :
fonte
sleep
aceitá-los.Acabei criando uma variante da resposta do swalog. Com o dele, você teve que esperar X segundos pela primeira iteração, também estou executando o meu em primeiro plano, então ..
fonte
Rápido, sujo e provavelmente perigoso para boot, mas se você é aventureiro e saber o que você está fazendo, colocar isso em
repeat.sh
echmod 755
-lo,Invoque-o com
./repeat.sh <command> <interval>
Meu senso de aranha diz que essa é provavelmente uma maneira maligna de fazer isso, meu senso de aranha está certo?
fonte
sleep $1; shift; "$@"
ou similar seria muito melhor.Você pode executar um script a partir do init (adicionando uma linha ao / etc / inittab). Este script deve executar seu comando, dormir pelo tempo que você deseja esperar até executar o script novamente e sair dele. O Init iniciará seu script novamente após a saída.
fonte
Maneira fácil de repetir um trabalho do crontab com um intervalo inferior a um minuto (exemplo de 20 segundos):
crontab: * * * * * script.sh
script.sh:
fonte
Você pode obter o poder do interpretador python do shell.
substitua cinco a qualquer momento (s) que desejar.
Atenção: o retorno use SHIFT + ENTER para retornar a entrada no shell. E não esqueça de digitar 4 recuo de ESPAÇO em cada linha no loop while.
fonte
python
'sos.system()
executa um shell para interpretar a linha de comando, então invocandopython
para executar conchas em um loop para executar um comando é periodicamente um pouco exagero. Você também pode fazer tudo no shell.Esta solução funciona no MacOSX 10.7. Funciona maravilhosamente.
No meu caso
ou
para limpar minha área de trabalho constantemente.
fonte
sleep
comando lá?while [ 0 ]
é uma maneira estranha de escrever um loop infinito; funciona porque otest
comando (também conhecido como[
) trata uma string não vazia como verdadeira.while : ; do ... ; done
é mais idiomático ou, se você preferir, pode usarwhile true ; do ... ; done
.Você pode obter esta função recursiva:
ou adicione um:
e chame o script.
fonte
Para executar repetidamente um comando em uma janela do console, geralmente executo algo como isto:
while true; do (run command here); done
Isso funciona para vários comandos, por exemplo, para exibir um relógio de atualização contínua em uma janela do console:
while true; do clear; date; sleep 1; done
fonte
fonte
Com
zsh
e umasleep
implementação que aceita argumentos de ponto flutuante:Ou para
forever
:Se o seu
sleep
não suportar flutuadores, você sempre poderá redefini-lo como um invólucro em tornozsh
dozselect
interno:fonte
... Gostaria de saber quantas soluções complicadas podem ser criadas ao resolver esse problema.
Pode ser tão fácil ...
coloque lá 1 linha ao final do arquivo como:
Se você deseja executar algo a cada 1 segundo, basta colocar lá:
e dentro desse arquivo.sh deve estar:
e isso é tudo!
APROVEITAR!
fonte
funciona para mim.
fonte