Powłoka: czy można opóźnić polecenie bez użycia polecenia „sleep”?
21
Czy są jakieś substytuty, alternatywy lub sztuczki do opóźniania poleceń bez użycia sleep? Na przykład wykonanie poniższej komendy bez użycia trybu uśpienia:
Nie ma innego powodu niż ciekawość. Pomyślałem, że interesujące byłoby poznanie alternatywnych rozwiązań. Myślę, że atmoże być jeden, ale nie mogłem znaleźć żadnych przykładów użycia.
user321697,
1
@ user321697 „at” ma zaplanować pojedyncze zadania. są one wykonywane przez usługę atd, więc nie wstrzymają skryptu powłoki. jednym z przypadków użycia at at może być zrobienie czegoś w określonym czasie (asynchronizacja) i utworzenie pliku znacznika po zakończeniu, podczas gdy skrypt czeka na pojawienie się tego pliku w pętli while. podobny efekt można osiągnąć, planując zadanie wysyłania skryptu SIGCONT, a następnie zamrażając skrypt, wysyłając sobie SIGSTOP.
Grega Bremec,
1
Przybyłem tutaj, oczekując, że wszyscy zasugerują blokadę. Jestem mile zaskoczony wszystkimi odpowiedziami.
Daan van Hoek
3
Re: „Ciekawość” - w unix.stackexchange.com/help/dont-ask , trzeba pamiętać, że wymóg „Należy zwrócić tylko praktyczne, odpowiada na pytania na podstawie rzeczywistych problemów, które możesz napotkać. ” - że to było dobrze otrzymane pomimo sprzeczności z tą wytyczną czyni to raczej rzadkim wyjątkiem.
Charles Duffy
Odpowiedzi:
17
Masz alternatywy dla sleep: Są ati cron. W przeciwieństwie do sleeptych, musisz podać czas, w którym chcesz je uruchomić.
Upewnij się, że atdusługa działa, wykonując service atd status.
Powiedzmy teraz, że jest godzina 11:17 UTC; jeśli trzeba wykonać polecenie na 11:25 UTC, składnia jest: echo "This is a test" | at 11:25.
Teraz pamiętaj, że atddomyślnie nie będzie rejestrować ukończenia zadań. Aby uzyskać więcej, zapoznaj się z tym linkiem . Lepiej, aby aplikacja miała własne logowanie.
Możesz zaplanować zadania w cron, aby uzyskać więcej informacji: man cronzobacz jego opcje lub crontab -edodaj nowe zadania. /var/log/cronmożna sprawdzić w celu uzyskania informacji o wykonywaniu zadań.
FYI sleep system call zawiesza bieżące wykonanie i planuje zapisanie przekazanego argumentu.
EDYTOWAĆ:
Jak wspomniano w @Gaius, możesz również dodać minuty czasu do atpolecenia, ale powiedzmy, że czas jest, 12:30:30a teraz uruchomiłeś harmonogram now +1 minutes. Mimo że podano 1 minutę, co przekłada się na 60 sekund, attak naprawdę nie czeka aż 12:31:30do wykonania zadania, a raczej wykonuje zadanie o 12:31:00. Jednostki czasu mogą być minutes, hours, days, or weeks. Aby uzyskać więcej informacjiman at
To nie jest prawda, możesz zaplanować pracę, powiedzmy teraz +1 minutę, aby biegła za minutę
Gaius
29
Dzięki bashwbudowanym funkcjom możesz:
coproc read -t 10&& wait "$!"|| true
Spać przez 10 sekund bez użycia sleep. coprocJest aby tak, że read„s stdin jest rura gdzie nic nigdy nie wyjdzie z. || truejest ponieważ waitstatus wyjścia będzie odzwierciedlał dostarczenie SIGALRM, które spowodowałoby zamknięcie powłoki, jeśli errexitopcja jest ustawiona.
W innych muszlach:
mkshi ksh93mają sleepwbudowane, nie ma sensu używać niczego innego (chociaż oba one również obsługują read -t).
zshobsługuje również read -t, ale ma również wbudowane opakowanie select(), więc możesz również użyć:
@JeffSchaller Unikałbym tego, ponieważ jest to zajęta pętla.
Stéphane Chazelas,
@ StéphaneChazelas Nie spodziewałbym się, że będzie to zajęta pętla - oczekiwałbym, że każda powłoka readzostanie zaimplementowana przy użyciu select (2) lub czegoś podobnego (co sugeruje, że odpowiedź na żądanie byłaby dobrą odpowiedzią na to pytanie). Wyrażam raczej zdziwienie niż zaprzeczenie, ale czy możesz wskazać na dalszą dyskusję na ten temat?
Norman Gray,
5
@NormanGray, /dev/zeroto plik zawierający nieskończoną ilość danych (NUL bajtów). readCzyta więc tyle, ile może podczas tych 10 sekund. Na szczęście, w przypadku, bashgdy nie obsługuje przechowywania bajtów NUL w jego zmiennych, nie zużyje to żadnej pamięci, ale nadal będzie pochłaniać zasoby procesora.
Stéphane Chazelas,
1
@NormanGray, jeśli zostanie uruchomiony z terminala, /dev/stdoutbędzie urządzeniem tty, więc będzie miał skutki uboczne (takie jak zatrzymanie skryptu, jeśli zostanie uruchomiony w tle) i zwróci, jeśli na przykład użytkownik naciśnie klawisz Enter. read -t 10 /dev/stdout | :działałby w systemie Linux, ale tylko w systemie Linux, podczas gdy coprocpowinien działać niezależnie od systemu operacyjnego.
Stéphane Chazelas,
7
Kilka innych pomysłów.
top -d10 -n2 >/dev/null
vmstat 102>/dev/null
sar 101>/dev/null
timeout 10s tail -f /dev/null
„Ukradłeś” mój pomysł na ograniczenie czasowe / przekroczenie limitu czasu .... +1
Rui F Ribeiro
1
Ohhhh, dzięki, byłem w sytuacji bez snu, top jest niesamowity!
Fire-Dragon-DoL
6
Ponieważ istnieją odpowiedzi, które sugerują skorzystanie z niestandardowej -t delayopcji read, oto sposób na odczytywanie limitów czasu w standardowej powłoce:
{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss";}
Nie stanie się tak, jeśli proces będzie wymagał uruchomienia bez interakcji lub w tle, prawda?
ss_iwe
Prawidłowo: Ale to nie było jedno z wymagań OP w pierwotnym pytaniu, więc wciąż ważna odpowiedź ... ;-)> :-)
Fabby
1
OP konkretnie podaje przykład (z sleep) i prosi o równoważną alternatywę bez. readPrzepraszam, więc się nie analizuje. ;)
AnoE,
@AnoE Odpowiedź Stéphane'a jest oczywiście najlepsza, moja jest tylko najstarsza --- press «enter» to continue --- ;-)
Fabby
4
W czasach mikrokomputerów z systemem BASIC opóźnienia były zwykle osiągane za pomocą pustej pętli:
FOR I = 1 TO 10000:NEXT
Tej samej zasady można użyć do wstawienia opóźnienia w skrypcie powłoki:
COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done
Oczywiście problemem związanym z tym podejściem jest to, że długość opóźnienia będzie się różnić w zależności od szybkości procesora (lub nawet na tej samej maszynie pod różnymi obciążeniami). W przeciwieństwie do sleeptego, prawdopodobnie spowoduje to również maksymalne obciążenie twojego procesora (lub jednego z jego rdzeni).
Pętle opóźniające są okropnym pomysłem na wszystko oprócz najkrótszych okresów uśpienia (kilka nanosekund lub cykli zegara w sterowniku urządzenia) na każdym nowoczesnym procesorze, który może obsługiwać system operacyjny podobny do Uniksa. tj. sen tak krótki, że procesor nie może pożytecznie nic zrobić podczas oczekiwania, np. zaplanować inny proces lub przejść w stan uśpienia o niskim poborze mocy przed wybudzeniem się po przerwie czasowej. Dynamiczna częstotliwość procesora uniemożliwia nawet skalibrowanie pętli opóźnień dla zliczeń na sekundę, z wyjątkiem minimalnego opóźnienia potencjalnie śpiącego znacznie dłużej przy niskich częstotliwościach zegara przed przyspieszeniem.
Peter Cordes,
Starożytne komputery miały zużycie energii znacznie mniej zależne od obciążenia. Nowoczesne procesory muszą dynamicznie wyłączać różne części układu tak bardzo, jak to możliwe, aby się nie stopiły (np. Wyłączają części jednostek wykonawczych FPU lub SIMD, gdy działa tylko kod całkowity, lub przynajmniej przesyłają sygnał zegara do części układu które nie muszą się przełączać). I przejście w stan uśpienia o niskiej mocy, gdy bezczynny (zamiast wirowania w nieskończonej pętli w oczekiwaniu na przerwania timera) jest również nowszy niż starożytne komputery, o których wspomniałeś.
Błędna konfiguracja zapory lub systemu nazw może spowodować znaczne dodatkowe opóźnienie.
spectras
1
127.0.0.1 ... @spectras
AnoE
1
Na szczęście nie jest już potrzebny, ponieważ system Windows obsługuje teraz tryb uśpienia natywnie.
Baldrickk,
1
@AnoE> rozwiązuje część systemu nazw, a nie część zapory. Chociaż nie jest to powszechne, można go skonfigurować tak, aby dyskretnie upuszczał polecenia ping na interfejs lokalny. Spowoduje to, że ping będzie czekać znacznie dłużej.
spectras
+1 za „miłe” wspomnienia
AC
0
Jeśli chcesz interaktywnie czekać na nową linię w pliku, to
tail -f
.
Czekasz na zmianę w systemie plików? Następnie użyj np
inotify / inoticoming
.
I są inne opcje, w zależności od tego, co masz na myśli przez „czekać”.
sleep
?at
może być jeden, ale nie mogłem znaleźć żadnych przykładów użycia.Odpowiedzi:
Masz alternatywy dla
sleep
: Sąat
icron
. W przeciwieństwie dosleep
tych, musisz podać czas, w którym chcesz je uruchomić.Upewnij się, że
atd
usługa działa, wykonującservice atd status
.Powiedzmy teraz, że jest godzina 11:17 UTC; jeśli trzeba wykonać polecenie na 11:25 UTC, składnia jest:
echo "This is a test" | at 11:25
.Teraz pamiętaj, że
atd
domyślnie nie będzie rejestrować ukończenia zadań. Aby uzyskać więcej, zapoznaj się z tym linkiem . Lepiej, aby aplikacja miała własne logowanie.Możesz zaplanować zadania w
cron
, aby uzyskać więcej informacji:man cron
zobacz jego opcje lubcrontab -e
dodaj nowe zadania./var/log/cron
można sprawdzić w celu uzyskania informacji o wykonywaniu zadań.FYI
sleep system call
zawiesza bieżące wykonanie i planuje zapisanie przekazanego argumentu.EDYTOWAĆ:
Jak wspomniano w @Gaius, możesz również dodać minuty czasu do
at
polecenia, ale powiedzmy, że czas jest,12:30:30
a teraz uruchomiłeś harmonogramnow +1 minutes
. Mimo że podano 1 minutę, co przekłada się na 60 sekund,at
tak naprawdę nie czeka aż12:31:30
do wykonania zadania, a raczej wykonuje zadanie o12:31:00
. Jednostki czasu mogą byćminutes, hours, days, or weeks
. Aby uzyskać więcej informacjiman at
na przykład:
echo "ls" | at now +1 minutes
źródło
Dzięki
bash
wbudowanym funkcjom możesz:Spać przez 10 sekund bez użycia
sleep
.coproc
Jest aby tak, żeread
„s stdin jest rura gdzie nic nigdy nie wyjdzie z.|| true
jest ponieważwait
status wyjścia będzie odzwierciedlał dostarczenie SIGALRM, które spowodowałoby zamknięcie powłoki, jeślierrexit
opcja jest ustawiona.W innych muszlach:
mksh
iksh93
mająsleep
wbudowane, nie ma sensu używać niczego innego (chociaż oba one również obsługująread -t
).zsh
obsługuje równieżread -t
, ale ma również wbudowane opakowanieselect()
, więc możesz również użyć:Jeśli chcesz zaplanować uruchamianie rzeczy z interaktywnej sesji powłoki, zobacz także
zsh/sched
moduł wzsh
.źródło
read -t 10 < /dev/zero || true
?read
zostanie zaimplementowana przy użyciu select (2) lub czegoś podobnego (co sugeruje, że odpowiedź na żądanie byłaby dobrą odpowiedzią na to pytanie). Wyrażam raczej zdziwienie niż zaprzeczenie, ale czy możesz wskazać na dalszą dyskusję na ten temat?/dev/zero
to plik zawierający nieskończoną ilość danych (NUL bajtów).read
Czyta więc tyle, ile może podczas tych 10 sekund. Na szczęście, w przypadku,bash
gdy nie obsługuje przechowywania bajtów NUL w jego zmiennych, nie zużyje to żadnej pamięci, ale nadal będzie pochłaniać zasoby procesora./dev/stdout
będzie urządzeniem tty, więc będzie miał skutki uboczne (takie jak zatrzymanie skryptu, jeśli zostanie uruchomiony w tle) i zwróci, jeśli na przykład użytkownik naciśnie klawisz Enter.read -t 10 /dev/stdout | :
działałby w systemie Linux, ale tylko w systemie Linux, podczas gdycoproc
powinien działać niezależnie od systemu operacyjnego.Kilka innych pomysłów.
źródło
Ponieważ istnieją odpowiedzi, które sugerują skorzystanie z niestandardowej
-t delay
opcjiread
, oto sposób na odczytywanie limitów czasu w standardowej powłoce:Argument
stty time
jest za dziesiąte sekundy.źródło
Korzystanie z wbudowanej zmiennej bash
$SECONDS
i pętli zajętości:źródło
bash
;zsh
imksh
miał podobne problemy, ale od tego czasu zostały naprawione)najstarsza sztuczka w książce:
Po prostu naciśnij, Entera będzie kontynuowane!
źródło
sleep
) i prosi o równoważną alternatywę bez.read
Przepraszam, więc się nie analizuje. ;)--- press «enter» to continue ---
;-)W czasach mikrokomputerów z systemem BASIC opóźnienia były zwykle osiągane za pomocą pustej pętli:
FOR I = 1 TO 10000:NEXT
Tej samej zasady można użyć do wstawienia opóźnienia w skrypcie powłoki:
COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done
Oczywiście problemem związanym z tym podejściem jest to, że długość opóźnienia będzie się różnić w zależności od szybkości procesora (lub nawet na tej samej maszynie pod różnymi obciążeniami). W przeciwieństwie do
sleep
tego, prawdopodobnie spowoduje to również maksymalne obciążenie twojego procesora (lub jednego z jego rdzeni).źródło
Nie ma wbudowanego, który robi to samo co
sleep
(chyba żesleep
jest wbudowany). Istnieją jednak inne polecenia, które będą czekać.Kilka to.
at
icron
: używane do planowania zadań w określonym czasie.inotifywait
: używane do oczekiwania na plik lub pliki do zmodyfikowania / usunięcia / dodania / itpźródło
at
?cron
przechowywać zadania wcrontab
, prawda? Gdzie sąat
przechowywane zaplanowane dane?Klasyk z Krainy Windows i partii:
źródło
Jeśli chcesz interaktywnie czekać na nową linię w pliku, to
.Czekasz na zmianę w systemie plików? Następnie użyj np
.I są inne opcje, w zależności od tego, co masz na myśli przez „czekać”.
źródło