Istnieje wbudowane polecenie Unix, repeat
którego pierwszym argumentem jest liczba powtórzeń polecenia, przy czym polecenie (z dowolnymi argumentami) jest określone przez pozostałe argumenty repeat
.
Na przykład,
% repeat 100 echo "I will not automate this punishment."
wyśle echo podany ciąg 100 razy, a następnie zatrzyma się.
Chciałbym podobną komendę - nazwijmy ją forever
- która działa podobnie, z tym wyjątkiem, że pierwszym argumentem jest liczba sekund na pauzę między powtórzeniami i powtarza się na zawsze. Na przykład,
% forever 5 echo "This will get echoed every 5 seconds forever and ever."
Pomyślałem, że zapytam, czy coś takiego istnieje, zanim to piszę. Wiem, że to jest jak 2-liniowy skrypt Perla lub Pythona, ale może jest to bardziej standardowy sposób. Jeśli nie, możesz opublikować rozwiązanie w swoim ulubionym języku skryptowym, w stylu Rosetta Stone .
PS: Być może lepszym sposobem na zrobienie tego byłoby uogólnienie repeat
polegające zarówno na powtarzaniu liczby powtórzeń (z -1 oznacza nieskończoność), jak i na liczbie sekund snu między powtórzeniami. Powyższe przykłady stałyby się wówczas:
% repeat 100 0 echo "I will not automate this punishment."
% repeat -1 5 echo "This will get echoed every 5 seconds forever."
źródło
type repeat
i dać mi znać, skąd pochodzi?repeat
jest wbudowanym poleceniem w csh i tcsh.Odpowiedzi:
Wypróbuj
watch
polecenie.Po to aby:
uruchomi polecenie co drugi (dobrze, technicznie, każdy sekund plus czas potrzebny na
command
uruchomienie jakowatch
(przynajmniejprocps
ibusybox
implementacje) po prostu śpi jedną sekundę między dwoma ciągamicommand
), na zawsze.Czy chcesz przekazać polecenie
exec
zamiastsh -c
, użyj-x
opcji:W systemie macOS można uzyskać
watch
z portów Mac :Lub możesz go uzyskać od Homebrew :
źródło
while true; do X; sleep Y; done
- Jest o wiele lepiej.cmdwatch
na FreeBSD (z portów:)sysutils/cmdwatch
.Grzmotnąć
while
+sleep
:Oto to samo, co skrócona jedna linijka (z poniższych komentarzy):
Używa
;
oddzielnych poleceń i używasleep 1
dowhile
testu, ponieważ zawsze zwraca true. Możesz umieścić więcej poleceń w pętli - wystarczy je oddzielić;
źródło
sleep
nie zawsze powraca prawda. Użyłem takich pętli (choć z większym opóźnieniem), ponieważ istnieje sposób, aby zakończyć je z wdziękiem zabijając proces uśpienia.Jest to tylko krótsza wersja innych
while+sleep
odpowiedzi, jeśli często wykonujesz tego rodzaju zadania jako codzienną rutynę, użycie tego pozwala uniknąć niepotrzebnych naciśnięć klawiszy, a jeśli wiersz poleceń zaczyna rozumieć dłużej, jest to nieco łatwiejsze. Ale ten zaczyna się od spania jako pierwszego.Jest to na ogół przydatne, jeśli chcesz podążać za czymś, co ma wyjście w jednym wierszu, np. Obciążenie maszyny:
źródło
while clear; do date; command;sleep 5; done
while sleep
kombinację, oszczędza naciśnięcia klawiszy!Jednym z problemów, na który natrafiły wszystkie dotychczasowe odpowiedzi, jest to, że czas wykonania polecenia może dryfować. Na przykład, jeśli wykonujesz
sleep 10
polecenie między, a wykonanie polecenia zajmuje 2 sekundy, będzie ono uruchamiane co 12 sekund; jeśli uruchomienie zajmuje zmienną ilość czasu, to w dłuższej perspektywie czas jego uruchomienia może być nieprzewidywalny.To może być właśnie to, czego chcesz; jeśli tak, skorzystaj z jednego z pozostałych rozwiązań lub skorzystaj z tego, ale uprość
sleep
połączenie.W przypadku jednominutowej rozdzielczości zadania cron będą uruchamiane o określonej godzinie, niezależnie od tego, jak długo zajmuje każde polecenie. (W rzeczywistości uruchomione zostanie nowe zadanie crona, nawet jeśli poprzednie nadal działa).
Oto prosty skrypt Perla, który śpi do następnego interwału, więc na przykład w odstępie 10 sekund polecenie może zostać uruchomione o 12:34:00, 12:34:10, 12:34:20 itd., Nawet jeśli samo polecenie zajmuje kilka sekund. Jeśli polecenie działa dłużej niż
interval
sekundy, następny przedział zostanie pominięty (w przeciwieństwie do crona). Przedział jest obliczany względem epoki, więc przedział 86400 sekund (1 dzień) będzie działał o północy czasu UTC.źródło
while :; do sleep 1m & command; wait; done
wait
zaczekają na wszystkie). Można to naprawić, zmieniającwait
nawait $!
, gdzie$!
jest PIDsleep
procesu. Opublikuj to jako odpowiedź, a ja go poprę. Ale generuje trochę obcego wyniku w interaktywnej powłoce.Myślę, że wszystkie dotychczasowe odpowiedzi są albo zbyt skomplikowane, albo zamiast tego odpowiedz na inne pytanie:
Prawdziwe pytanie brzmiało:
Są to dwie bardzo różne rzeczy, gdy polecenie wymaga czasu na zakończenie.
Weźmy na przykład skrypt
foo.sh
(udawaj, że jest to program, który zajmuje kilka sekund).Chcesz uruchomić to co sekundę, a większość sugerowałaby
watch -n1 ./foo.sh
, lubwhile sleep 1; do ./foo.sh; done
. Daje to jednak wynik:Co nie jest dokładnie uruchamiane co sekundę. Nawet z
-p
flagą, jakman watch
sugeruje strona, może to rozwiązać, wynik jest taki sam.Łatwym sposobem na wykonanie pożądanego zadania, na które niektórzy się dotykają, jest uruchomienie polecenia w tle. Innymi słowy:
I to wszystko.
Możesz uruchomić go co 500 ms z
sleep 0.5
, lub co masz.źródło
while :; do sleep 1 & ./foo.sh; wait; done
date +"%H:%M:%S.%N"
w foo.sh zobaczyć jak frakcja będzie powoli wzrastać na każdej pętli.W
bash
:(
echo
można zastąpić dowolnym poleceniem ...Lub w
perl
:Gdzie
print "I will not automate this punishment in absurdum.\n"
można zastąpić „dowolnym” poleceniem otoczonym backticks (`).I na chwilę dodaj
sleep
instrukcję w pętli for:i
źródło
while [ 0 ]
to zły sposób na napisanie tego. Oznacza0
to, że jest łańcuchem o długości> 0.while [ 1 ]
Lubwhile [ jeff ]
zrobiłby to samo. Lepiej pisaćwhile true
.while :
Ostatnie bash> = 4.2 pod najnowszym jądrem Linuksa, odpowiedź oparta.
Aby ograniczyć czas wykonania, nie ma widelców ! Używane są tylko wbudowane.
W tym celu używam
read
wbudowanej funkcji zamiastsleep
. Niestety nie będzie to działać w przypadku sesji notty .Funkcja szybkiego uderzenia „
repeat
” zgodnie z żądaniem:Mały test z podanymi ciągami:
W zależności od szczegółowości i czasu trwania przesłanego polecenia ...
W najnowszych jądrach Linuksa istnieje plik
/proc/timer_list
zawierający informacje o czasie w nanosekundach.Jeśli chcesz uruchomić polecenie dokładnie raz na sekundę, Twoje polecenie musi zakończyć się w niecałą sekundę! I stamtąd musisz
sleep
tylko resztę bieżącej sekundy.Jeśli opóźnienie jest ważniejsze, a twoje polecenie nie wymaga znacznego czasu, możesz:
Ale jeśli Twoim celem jest uzyskanie drobniejszej ziarnistości, musisz:
Użyj informacji w nanosekundach, aby poczekać do początku sekundy ...
W tym celu napisałem małą funkcję bash:
Po ich uzyskaniu możesz:
uruchomić
${command[@]}
bezpośrednio w wierszu poleceń, niż porównać zto musi dać dokładnie taki sam wynik.
Wynajmuje funkcję bash „
repeat
” zgodnie z żądaniem:Możesz to źródło:
Następnie spróbuj:
źródło
read -t
jest wbudowany , asleep
nie jest. Może to mieć efekt graniczny (tj. Uderzenie [klawisz: powrót] cicho przerywa sen ), ale można to wyleczyć, testując$foo
Chcesz wypróbować to (Bash)?
źródło
repeat
jest specyficzny dla csh i tcsh.Perl
źródło
Bash i niektóre z jego pokrewnych powłok mają wygodny
(( ... ))
zapis, w którym można oceniać wyrażenia arytmetyczne.Tak więc, jako odpowiedź na twoje trzecie wyzwanie, w którym zarówno liczba powtórzeń, jak i opóźnienie między nimi powinny być konfigurowalne, oto jeden ze sposobów, aby to zrobić:
Ta odpowiedź cierpi również na przesunięcie czasowe ujęte w odpowiedzi Keitha .
źródło
Jak wspomniano przez gbrandt, jeśli
watch
polecenie jest dostępne, zdecydowanie użyj go. Jednak niektóre systemy uniksowe nie mają zainstalowanej domyślnie (przynajmniej nie działają tam, gdzie pracuję).Oto inne rozwiązanie z nieco inną składnią i wyjściem (działa w BASH i SH):
Edycja: usunąłem część „.” w ostatnim zestawieniu echa ... pozostałość po moich dniach Perla;)
źródło
while [ 1 ]
działa tylko, ponieważ 1 jest traktowany jak ciąg znaków, tak jakwhile [ -n 1 ]
.while [ 0 ]
lubwhile [ jeff ]
zrobiłby to samo.while true
ma znacznie większy sens.Jeśli nie zamierzasz wyświetlać komunikatu na ekranie i możesz sobie pozwolić na powtórzenie zadania w minutach , być może najlepszym narzędziem będzie crontab . Na przykład, jeśli chcesz wykonywać polecenie co minutę, w
crontab
pliku zapisujesz coś takiego :Zapoznaj się z samouczkiem dla dalszego przykładu. Ponadto możesz łatwo ustawić czasy za pomocą Crontab Code Generator .
źródło
Co jeśli mielibyśmy oba?
Oto pomysł: tylko „interwał” powtarza się na zawsze. Z „interwałem” i „czasem” powtarza tę liczbę razy, oddzielonych „interwałem”.
Użycie :
Algorytm będzie więc:
W związku z tym :
źródło
sleep
że je akceptuje.Skończyło się na tym, że stworzyłem wariant odpowiedzi Swalog. Z nim musiałeś poczekać X sekund na pierwszą iterację, ja również prowadzę moją na pierwszym planie, więc ...
źródło
Szybkie, brudne i prawdopodobnie niebezpieczne do uruchomienia, ale jeśli masz ochotę na przygodę i wiesz, co robisz, włóż to
repeat.sh
ichmod 755
to,Wywołaj to za pomocą
./repeat.sh <command> <interval>
Mój paskudny zmysł mówi, że jest to prawdopodobnie zły sposób, czy mój pajęczy zmysł, prawda?
źródło
sleep $1; shift; "$@"
lub podobny byłby znacznie lepszy.Możesz uruchomić skrypt z init (dodając wiersz do / etc / inittab). Ten skrypt musi uruchomić polecenie, spać przez czas, który chcesz poczekać, aż uruchom ponownie skrypt i wyjść z niego. Init uruchomi skrypt ponownie po wyjściu.
źródło
Łatwy sposób na powtórzenie zadania z crontab w odstępie krótszym niż jedna minuta (przykład 20 sekund):
crontab: * * * * * script.sh
script.sh:
źródło
Moc można uzyskać z interpretera Pythona z powłoki.
wymień pięć w dowolnym czasie (sek.), jaki chcesz.
Uwaga: return użyj SHIFT + ENTER, aby zwrócić dane wejściowe w powłoce. I nie zapomnij wpisać wcięcia 4 SPACJA w każdej linii w pętli while.
źródło
python
sos.system()
wykonuje powłokę w celu interpretacji wiersza poleceń, więc wywoływaniepython
powłoki w pętli w celu okresowego uruchamiania polecenia jest nieco przesadzone. Równie dobrze możesz zrobić wszystko w powłoce.To rozwiązanie działa w systemie MacOSX 10.7. Działa cudownie.
W moim przypadku
lub
aby stale sprzątać mój pulpit.
źródło
sleep
komendę?while [ 0 ]
jest dziwnym sposobem na napisanie nieskończonej pętli; działa, ponieważtest
polecenie (znane również jako[
) traktuje niepusty ciąg znaków jako prawdziwy.while : ; do ... ; done
jest bardziej idiomatyczny lub jeśli wolisz, możesz go użyćwhile true ; do ... ; done
.Możesz użyć tej funkcji rekurencyjnej:
lub dodaj:
i wywołaj skrypt.
źródło
Aby wielokrotnie uruchamiać polecenie w oknie konsoli, zwykle uruchamiam coś takiego:
while true; do (run command here); done
Działa to również w przypadku wielu poleceń, na przykład w celu wyświetlania stale aktualizowanego zegara w oknie konsoli:
while true; do clear; date; sleep 1; done
źródło
źródło
Za pomocą
zsh
isleep
implementacji, która akceptuje argumenty zmiennoprzecinkowe:Lub dla
forever
:Jeśli urządzenie
sleep
nie obsługuje pływaków, zawsze można zdefiniować ją jako owinięcia wokółzsh
„szselect
wbudowanego:źródło
... Zastanawiam się, ile skomplikowanych rozwiązań można stworzyć, rozwiązując ten problem.
To może być takie proste ...
umieść tam 1 następną linię na końcu pliku, np .:
Jeśli chcesz uruchomić coś co 1 sekundę, po prostu umieść tam:
a wewnątrz tego pliku.sh powinno być:
i to wszystko!
CIESZYĆ SIĘ!
źródło
pracuje dla mnie.
źródło