Czy powtarzać polecenie co x odstęp czasu w terminalu?


142

Jak mogę powtarzać polecenie w każdym przedziale czasu, aby umożliwić mi uruchamianie poleceń w celu sprawdzenia lub monitorowania katalogów?

Skrypt nie jest potrzebny, potrzebuję tylko prostej komendy do wykonania w terminalu.

Odpowiedzi:


219

Możesz użyć watchpolecenia, zegarek służy do uruchamiania dowolnego wyznaczonego polecenia w regularnych odstępach czasu.

Otwórz terminal i wpisz:

watch -n x <your command>

zmień x na żądany czas w sekundach.

Aby uzyskać dodatkową pomoc w korzystaniu z watchpolecenia i jego opcji, uruchom man watchlub odwiedź ten link .

Na przykład: co 60. na tym samym terminalu będzie wyświetlana zawartość katalogu Desktop, aby można było wiedzieć, czy nastąpiły jakieś zmiany:

watch -n 60 ls -l ~/Desktop

34
+1, ale zachowaj ostrożność podczas korzystania z rozszerzeń. Na przykład wypróbuj różnicę pomiędzy watch -n 1 'echo $COLUMNS'i watch -n 1 echo $COLUMNSpodczas zmiany rozmiaru terminala - ten pierwszy jest rozwijany co sekundę, ale drugi jest rozszerzany tylko raz przed uruchomieniem watch.
l0b0

To działa jak urok ! Ty nux

Problem z tym rozwiązaniem polega na tym, że nie można uruchamiać oglądania jako procesu i po prostu pozostawić go uruchomionego w tle (na przykład z & disown)
Cestarian

2
Czy jest jakiś sposób na użycie watchpolecenia typu „włączona historia”? Uwielbiam używać watch, ale czasami wolałbym zobaczyć dziennik poprzednich wykonań, zamiast tylko ostatniego. I tak, wiem, że mogę to zrobić za pomocą skryptów ( while true), ale korzystanie z watchnarzędzia jest o wiele czystsze!
rinogo

działało to dla prostszych poleceń, ale w przypadku łańcuchowych poleceń potokowych nie działało to dla mnie .. następna była komenda, której próbowałem => cat api.log | grep „woła” | wc -l
Sudip Bhandari

90

Możesz także użyć tego polecenia w terminalu, oprócz odpowiedzi nux:

while true; do <your_command>; sleep <interval_in_seconds>; done

Przykład

while true; do ls; sleep 2; done

To polecenie wydrukuje wydruk lsw odstępie 2 sekund.

Użyj Ctrl+, Caby zatrzymać proces.

Istnieje kilka wad watch

  • Nie można używać żadnych aliasowanych poleceń.
  • Jeśli dane wyjściowe dowolnego polecenia są dość długie, przewijanie nie działa poprawnie.
  • Występują problemy z ustawieniem maksymalnego odstępu czasu powyżej określonej wartości.
  • watchzinterpretuje sekwencje kolorów ANSI przekazując znaki zmiany znaczenia za pomocą -club --color. Na przykład wyjście pygmentizebędzie działać, ale nie powiedzie się ls --color=auto.

W powyższych okolicznościach może się to wydawać lepszą opcją.


watchistnieje dla tego, to jest trochę bezużyteczne powiedziałbym
Bruno Pereira

14
Nie twierdzę, że tej odpowiedzi należy użyć na pierwszym miejscu. watchjest dobry w większości przypadków. Dlatego na początku wspomniałem „oprócz odpowiedzi Nux”. Ale z kilkoma problemami jest watchna przykład Nie można używać żadnych aliasowanych poleceńwatch . Weźmy na przykład llalias, ls -laFale nie można go używać z watch. Również w przypadku, gdy wyjście dowolnego polecenia jest dość długie, będziesz mieć problemy z przewijaniem za pomocą watch. W tych kilku szczególnych przypadkach odpowiedź ta może wydawać się lepszą opcją.
souravc

@souravc Moja wersja watchco najmniej zezwala na opcje -club --colordla kolorowych wyników.
Lily Chung,

8
while sleep xjest lepszy - łatwiej zabijać.
d33tah

3
Jest to miła alternatywa i, w przeciwieństwie do watch, pozwala zachować historię poleceń.
adelriosantiago

34

Chciałem tylko dodać odpowiedzi do souravc i nux :

  1. Chociaż watchbędzie działał idealnie na Ubuntu, możesz tego uniknąć, jeśli chcesz, aby Twój „Unix-fu” był czysty - na przykład na FreeBSD, watch to polecenie „szpiegować na innej linii tty”.
  2. while true; do command; sleep SECONDS; doneposiada również zastrzeżenie - to polecenie może być trudniejsze do zabicia za pomocą CTR + C . Może wolisz while sleep SECONDS; do command; done- jest nie tylko krótszy, ale także łatwiejszy do przerwania. Zastrzeżenie polega na tym, że najpierw będzie spało, a następnie uruchomi polecenie, więc musisz poczekać, SECONDSzanim nastąpi pierwsze wystąpienie polecenia.

2
Mam nadzieję, że jest to akceptowalne jako odpowiedź zamiast komentarza - chciałem tu pokazać inne rozwiązanie, a komentowanie w rzeczywistości zwróciłoby na mnie mniej uwagi.
d33tah

Dlaczego dokładnie ma to znaczenie, w którym sleepmiejscu znajduje się whilepętla? Nie mogłem znaleźć żadnej różnicy, Ctrl + C natychmiast przerwał pętlę, bez względu na wszystko.
deser

@ deser: chyba zależy od tego, co próbujesz się wyrwać. Normalnie, ctrl + c po prostu zabije twoje commandi sleepzłamie tylko jeśli zabijesz true.
d33tah

11

Brzmi jak idealne zadanie dla crondemona, które pozwala na uruchamianie okresowych poleceń. Uruchom crontab -epolecenie, aby rozpocząć edycję konfiguracji crona użytkownika. Jego format jest udokumentowany w crontab (5) . Zasadniczo masz pięć powiązanych z czasem, oddzielonych spacjami pól, po których następuje polecenie:

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

Na przykład, jeśli chcesz uruchamiać skrypt w języku Python w każdy wtorek, o 11:00:

0 11 * * 1 python ~/yourscript.py

Istnieją również specjalne nazwy, które zastępują czas, np @reboot. Bardzo pomocne, jeśli chcesz utworzyć katalog tymczasowy. Z mojego crontab (wymienionego z crontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"

4
Pytanie dotyczy tego, jak co jakiś czas uruchamiać coś w terminalu. cronbiegnie za kulisami, a nie w terminalu
północny bradley,

5

Jeśli monitorujesz system plików, to inotifywaitjest genialny i z pewnością powoduje mniejsze obciążenie systemu.

Przykład:

W 1. terminalu wpisz to polecenie:

$ inotifywait .

Następnie w drugim terminalu dowolne polecenie, które wpływa na bieżący katalog,

$ touch newfile

Następnie w oryginalnym terminalu inotifywait obudzi się i zgłosi zdarzenie

./ CREATE newfile2

Lub w pętli

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.

użytkownik powiedział ci, że nie ma skryptu, a może nie chce niczego monitorować
oprócz

3
Nie powiedziałem mu, żeby napisał skrypt, zasugerowałem, że jeśli zapętlają się w celu obserwowania określonego zdarzenia w systemie plików, to inotifywait jest użyteczny i zużywa mniej zasobów niż powtarzanie polecenia. Często uruchamiam kilka poleceń w wierszu poleceń, np. Czy grep something InALogFile|lessto skrypt?
X Tian

to dobra odpowiedź, spróbuj go edytować, aby wyglądać prostiej.
nux

3
Co może być prostsze niż .nie mogę pominąć polecenia.
X Tian

Dzięki @XTian, ​​świetne polecenie. Widziałem też teraz na stronie podręcznika, które można dodawać, -maby stale monitorować bez pętli.
yoniLavi

4

Możesz utworzyć własne repeatpolecenie, wykonując następujące kroki; kredyty tutaj :

Najpierw otwórz .bash_aliasesplik:

$ xdg-open ~/.bash-aliases

Po drugie, wklej te linie na dole pliku i zapisz:

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

Po trzecie, zamknij i ponownie otwórz terminal lub wpisz:

$ source ~/.bash_aliases

Gotowe ! Możesz teraz używać tego w następujący sposób:

$ repeat 5 echo Hello World !!!

lub

$ repeat 5 ./myscript.sh

w linii xdg-open ~ / .bash-aliasses jest mała literówka. powinno być: xdg-open ~ / .bash_aliases (tj.: podkreślenie)
ssinfod

4

możesz użyć crontab. uruchom polecenie crontab -ei otwórz je za pomocą preferowanego edytora tekstu, a następnie dodaj ten wiersz

*/10 * * * *  /path-to-your-command

Spowoduje to uruchomienie polecenia co 10 minut

* */4 * * *  /path-to-your-command

Spowoduje to uruchomienie polecenia co 4 godziny

Inne możliwe rozwiązanie

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

X liczbę powtórzeń.

Y czas oczekiwania powtórzyć.

Przykład:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done

Dlaczego to poprawa? Właśnie dodałeś dodatkowy, niepotrzebny krok, zapisując polecenie jako zmienną. Jedyne, co to robi, to: i) wydłużenie wpisywania ii) zmusza cię do używania tylko prostych poleceń, bez potoków i przekierowań itp.
terdon

Usuń dodatkową zmienną
Maythux

3

Innym problemem związanym z zaproponowanym powyżej podejściem „obserwuj” jest to, że wyświetla wynik dopiero po zakończeniu procesu. „date; sleep 58; date” wyświetli 2 daty dopiero po 59 sekundach ... Jeśli zaczniesz coś działać przez 4 minuty, które wyświetlają powoli wiele stron treści, tak naprawdę nie zobaczysz.

Z drugiej strony, problem związany z podejściem „while” polega na tym, że nie bierze on pod uwagę czasu trwania zadania.

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

Dzięki temu skrypt będzie uruchamiany co minutę, czasem może zająć 1m40. Więc nawet jeśli cron będzie mógł uruchamiać go co minutę, tutaj nie będzie.

Aby więc zobaczyć wynik w powłoce podczas generowania i poczekać na dokładny czas żądania, musisz spojrzeć na czas przed i po oraz zapętlić się z chwilą.

Coś jak:

while ( true ); do
  echo Date starting `date`
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))`
  echo Before waiting `date`
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
  echo Done waiting `date`
done

Spowoduje to wygenerowanie:

Jak widać, polecenie jest uruchamiane co minutę:

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

Więc po prostu zamień echo $(( ( RANDOM % 30 ) + 1 ))komendę „uśpienie ” na to, co chcesz, i będzie ono uruchamiane na terminalu / powłoce dokładnie co minutę. Jeśli chcesz mieć inny harmonogram, po prostu zmień „60” sekund na to, czego potrzebujesz.

Krótsza wersja bez linii debugowania:

while ( true ); do
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))` # Place you command here
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
done

Odpowiadanie sobie ... Jeśli twoje polecenie zajmie więcej niż skonfigurowane opóźnienie, $ DELAY otrzyma wartość ujemną, a polecenie uśpienia zakończy się niepowodzeniem, więc skrypt natychmiast uruchomi się ponownie. Musisz być tego świadomy.
jmspaggi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.