Ciągle ponownie wykonuj polecenie, gdy zakończy się w Bash

62

Próbuję wymyślić prosty sposób ponownego wykonywania polecenia za każdym razem, gdy kończy się, z dowolnego powodu (błąd lub inny).

Jaki byłby najlepszy sposób na to?

EDYCJA: Wcześniej nie byłem wystarczająco jasny. Potrzebuję kolejnej realizacji, aby poczekać, aż zakończy się poprzednia.

EDYCJA 2: Prawie wszystkie odpowiedzi działają świetnie. Pomyślałem, że większość odpowiedzi albo rozwinie proces, albo wykona go ponownie tylko raz, żadna z nich nie jest pożądana.


źródło
1
Nadal nie jesteś pewien. Byłoby pomocne, gdybyś wspomniał o tym, jaki program wykonujesz.
Daniel Beck
1
-1 To pytanie nie pokazuje żadnego wysiłku badawczego, ponieważ użytkownik skomentował, że odpowiedzi nie działały, zamiast próbować robić to, co sugerują.
Daniel Beck

Odpowiedzi:

39

Tworzy to nieskończoną pętlę, wykonującą commandsię w kółko.

while :
    do
        command
done
Dennis
źródło
Zobacz edycję oryginalnego pytania. Muszę powtarzać to w kółko, nie tylko raz.
8
@calcifer Ta odpowiedź działa całkiem dobrze. W twoim programie jest coś niezwykłego, czego żaden z czterech dotychczasowych użytkowników nie spodziewał się i nie wspomniałeś o tym.
Daniel Beck
@calcifer jest to nieskończona pętla. powtarza się aż do końca czasu (no cóż, dopóki skrypt i tak nie zostanie zakończony)
Nate Koppenhaver,
1
Mój zło, myślałem, że to (i wszystkie inne odpowiedzi) rozwidlą proces lub ponownie go wykonają tylko raz, z których żadna nie jest pożądana. Tak, ta odpowiedź działa. Dzięki.
1
wersja jednoliniowa: while true; do echo 'Hit CTRL+C'; sleep 1; donedzięki cyberciti.biz/faq/bash-infinite-loop
jk2K 11.11.18
107

watchKomenda będzie powtarzać polecenia zawsze w odstępie określonym:

watch -n0 <command>

Ustawienie wartości -nzero powoduje, że interwał jest zerowy (myślę, że to naprawdę 0,1 sekundy).

watch ma również dodatkowe zalety wyrównania wydruku, dzięki czemu zmiany wizualne można łatwo zobaczyć, a także przełącznik do podświetlania zmian z ostatniego uruchomienia.

Odniesienie: strona man watch :

Watch uruchamia polecenie wielokrotnie, wyświetlając jego wynik (pierwszy screenfull). Pozwala to obserwować zmiany wyników programu w czasie. Domyślnie program jest uruchamiany co 2 sekundy; użyj -n lub --interval, aby określić inny interwał.

zegarek będzie działał do momentu przerwania.

Paweł
źródło
Zobacz edycję oryginalnego pytania.
6
Wszystkie dotychczasowe odpowiedzi tak robią, łącznie z tą jedną. Linux nie rozwidli się, chyba że specjalnie o to poprosisz.
Paul
Dzięki nie wiedziałem o rozwidleniu.
Nie widzę żadnych danych wyjściowych przy użyciu tej metody.
Raffi Khatchadourian
@RaffiKhatchadourian Czy mówisz, że jeśli robisz watch lsw katalogu zawierającym pliki, nic nie dostajesz?
Paul
17

Prostym rozwiązaniem byłoby:

yourcommand; !#

;rozdziela polecenia, pozwalając na wiele poleceń w jednym wierszu ( Bash: Listy )

!#każe bashowi „powtórzyć wszystko, co do tej pory napisałem w tym wierszu” ( Bash: Design-Event )

Niebieskie niebo
źródło
1
Przepraszam, nie byłem wystarczająco jasny. Muszę powtarzać to w kółko, nie tylko raz.
Dzięki za to, szukałem tego, zwłaszcza że yourcommand; !!wydaje się, że tak naprawdę nie działa z poleceniami w tej samej linii !#. Twoje zdrowie!
sdaau
; !#nie działało na ZSH, po prostu rozszerza oświadczenie zasadniczo klonując je, nie uruchamia go
odrzucił
7

Możesz planować z wyprzedzeniem podczas wykonywania polecenia (pod warunkiem, że nie jest ono interaktywne) i wprowadzić, !!który ponownie wykona poprzednie polecenie. Działa to np ping -c 5. Podczas .


Możesz także zdefiniować funkcję w bash:

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

Aby go zachować, zapisz go w ~/.bashrc.

Następnie możesz uruchomić polecenie w następujący sposób:

repeat ping -c5 heise.de

Jeśli jest to określone polecenie, które chcesz wielokrotnie wykonywać (a nie np. Dowolne polecenie), możesz zastąpić "$@"w tym fragmencie swoim rzeczywistym poleceniem i repeat_pingzamiast tego nazwać funkcję np .


Aby stworzyć nieskończoną pętlę, możesz zrobić to, co sugeruje @Dennis. Zalecam dodanie okresu oczekiwania, jeśli zamierzasz użyć tego w interaktywnej powłoce, takiej jak ta:

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

W przeciwnym razie przerywanie tej nieskończonej pętli jest raczej niewygodne Ctrl-Z.

Daniel Beck
źródło
Zobacz edycję oryginalnego pytania.
6
@calcifer Wykonania te czekają na powrót wywołania programu. Czy Twój program odłącza się od powłoki i wraca, zanim zakończy działanie?
Daniel Beck
Mój zło, myślałem, że to (i wszystkie inne odpowiedzi) rozwidlą proces lub ponownie go wykonają tylko raz, z których żadna nie jest pożądana. Tak, ta odpowiedź działa. Dzięki.
4

Nadaj whilepętli warunek logiczny, taki jak:

#!/bin/bash

while true; do

    do_something && wait

done

Będzie to wykonywane w kółko, dopóki bash nie otrzyma sygnału do zakończenia procesu. Zwykle w formie ctrl+c.

Możesz także użyć watchpolecenia do wielokrotnego uruchamiania skryptu. Na przykład prosty zegar w twoim terminalu bash watchmoże wyglądać następująco:

$ watch -t -n1 date +%T

Ta -topcja informuje, watchaby nie wyświetlać tytułu uruchomionego procesu. Zapewnia to czyste wyjście tylko z powtarzanego polecenia. Ta -n1opcja każe zegarkowi powtarzać się co nsekundę. W takim przypadku -n1będą odstępy 1sekundowe. Następnie date +%Tpolecenie pokazuje czas w momencie zakończenia polecenia. Wykonanie tego polecenia da ci aktywny zegar w twoim terminalu.

I jeszcze jedna metoda, której nie ma w żadnej innej odpowiedzi, byłaby nieskończonym wywołaniem funkcji.

do_something() { do_something }; do_something && wait

Jest to w zasadzie to samo, co whilepętla boolowska tylko przy użyciu rekurencyjnych wywołań funkcji.

(edytuj) Aby mieć na uwadze zasoby twojego komputera, dodałem && waittak, że za każdym razem, gdy proces jest uruchamiany, pętle będą „czekać”, aż proces zakończy się ze statusem wyjścia 0 przed następną iteracją. Jest to przydatne w interaktywnym skrypcie powłoki.


źródło
1
Istnieje whileprzykład pętli, ale nie używa on trueskładni boolowskiej . Jest watchprzykład, ale nie daje wielu przydatnych składni. Rozumiem tych, dla których może pomóc. Chciałem nadać im praktyczną przydatność. whileLogiczna pętla może być też falsei nie wykonywać dopóki warunek jest spełniony nieprawdziwe. Jest to całkiem przydatne.
1
@ Spittin'IT Dodano metodę, która nie jest używana w innych odpowiedziach dla Twojej wygody.
W porządku i rozumiem ... Właśnie komentowałem, przechodząc przez moduł recenzji, ale miła edycja i kontynuacja !!
Pimp Juice IT,
Jak działa ifponowne wykonywanie?
Kamil Maciorowski
Dobra uwaga Kamil. Zapomniałem zrobić to rekurencyjne lol. Naprawiono edycję za pomocą funkcji wywołującej się w ifinstrukcji.
0

To kolejna metoda, której używam do powtarzania polecenia w bash. Dla niektórych może to zabrzmieć głupio, ponieważ nie wymaga napisania scenariusza i może być znane wielu. Ale myślę, że warto o tym wspomnieć, ponieważ jest szybki i przyjazny dla początkujących, w tym sensie, że nie ma wiele składni do zapamiętania. Testowałem to tylko w gnome-terminal Ubuntu i inne terminale mogą tego nie obsługiwać.

  1. Wpisz polecenie w terminalu jeden raz.
  2. Wybierz polecenie zawierające znak nowej linii za pomocą myszy.
  3. Skopiuj zaznaczenie za pomocą Ctrl-Insert lub menu kontekstowego (zwykle dostępne po kliknięciu prawym przyciskiem myszy).
  4. Użyj Shift-Insert, aby wkleić tyle razy, ile chcesz uruchomić polecenie.

Nie musisz czekać, aż wkleisz wszystkie polecenia. Wklejone polecenia wpadają do kolejki i wykonują je jedna po drugiej.

jayadeepk
źródło
0

Dzisiaj czuję się pyskaty.

Przeczytaj jeden z nieskończonych strumieni i potokuj go xargs

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

Jeśli chcesz zrobić sobie przerwę, prawdopodobnie będziesz musiał wykonać sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
Jefferey Cave
źródło