Terminând o buclă infinită

Am o comandă pe care vreau să o rulez automat de fiecare dată când se termină, așa că am rulat așa ceva:

while [ 1 ]; do COMMAND; done; 

dar dacă nu pot „opri bucla cu Ctrl-c deoarece asta ucide doar COMMAND și nu întreaga buclă.

Cum aș realiza ceva similar, dar pe care îl pot opri fără a fi nevoie să închid terminalul?

Comentarii

  • Dacă ‘ m în bash folosesc doar Ctrl-Z pentru a opri jobul și apoi ” ucide% 1 ” pentru a-l ucide.
  • Așteptați … Linus a fost citat spunând: „Știm cu toții că Linux este minunat … face bucle infinite în 5 secunde. ” – așa că … așteaptă încă câteva secunde, ar trebui să se finalizeze.
  • @PaulCager a funcționat și pentru mine! De ce funcționează acolo unde face Ctrl-C nu?
  • @cirosantilli ucide lucrarea exterioară (bash ” wrapper „). În unele situații, ‘ nu a ucis imediat ” COMANDA „, de exemplu , dacă îl fundalizați, se poate strecura în trecut, chiar dacă părintele ‘ este mort. Dar bucla este moartă, iar ‘ este partea importantă.

Răspuns

Verificați starea de ieșire a comenzii. Dacă comanda a fost terminată de un semnal, codul de ieșire va fi 128 + numărul semnalului. Din documentația online GNU pentru bash :

În scopul shell-ului, o comandă care iese cu un statut de ieșire zero a reușit. O stare de ieșire diferită de zero indică eșec. Această schemă aparent contra-intuitivă este utilizată, astfel încât există un mod bine definit de a indica succesul și o varietate de moduri de a indica diferite moduri de eșec. Când o comandă se termină pe un semnal fatal al cărui număr este N, Bash folosește valoarea 128 + N ca stare de ieșire.

POSIX specifică, de asemenea, că valoarea unei comenzi care a fost terminată de un semnal este mai mare de 128, dar nu pare să precizeze valoarea exactă a acestuia, așa cum face GNU:

Starea de ieșire a unei comenzi care a încetat deoarece a primit un semnal va fi raportată ca fiind mai mare de 128.

De exemplu, dacă întrerupeți o comandă cu control-C, codul de ieșire va fi 130, deoarece SIGINT este semnalul 2 pe sistemele Unix. Deci:

while [ 1 ]; do COMMAND; test $? -gt 128 && break; done 

Comentarii

  • De menționat că acest lucru nu este garantat, de fapt, multe aplicații nu vor face acest lucru.
  • @Kyle Jones: puteți face legătura cu documentele POSIX / GNU care menționează acest lucru?
  • @cirosantilli Gata.
  • @ KyleJones mulțumesc! Încă în practică nu funcționează pentru COMMAND = paplay alert.ogg, poate pentru că paplay gestionează semnalul?
  • @cirosantilli Da, acesta este ‘ motivul. Dacă un proces gestionează semnalul și renunță, ‘ este diferit de procesul care este încheiat de un semnal neprelucrat.

Răspuns

Puteți opri și plasa lucrarea în fundal în timp ce rulează folosind ctrl + z . îți poate ucide jobul cu:

$ kill %1 

Unde [1] este numărul jobului tău.

Comentarii

  • Consultați și acest răspuns pentru explicații și multe altele.
  • Acest răspuns relativ recent funcționează pur și simplu. Trebuie să fie votat în sus. +1
  • M-ați ajutat foarte mult. Acesta este ceea ce am căutat în această întrebare 🙂

Răspuns

Aș spune că ar putea fi cel mai bine să vă puneți bucla infinită într-un script și să gestionați semnalele acolo. Aici este „punctul de plecare de bază . Sunt sigur că veți dori să îl modificați pentru a se potrivi. Scriptul folosește trap pentru a prinde ctrl c (sau SIGTERM), elimină comanda (am „folosit sleep aici ca test) și iese.

cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done 

Comentarii

  • Drăguț. Iată ‘ cum am folosit acest sfat pentru a crea un împachetare netcat de pornire automată: trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
  • dacă adăugați această abordare trap la același script (bash) cu bucla infinită de ucis, utilizați $$ în loc de $! (vezi aici )

Răspuns

În general, țin apăsat Ctrl-C . Mai devreme sau mai târziu se va înregistra între COMMAND” s și astfel încheiați bucla while. Poate că există o modalitate mai bună.

Comentarii

  • Nu știu sigur de ce, dar eșuează pentru anumite COMENZI precum paplay pe un fișier 1s .
  • A funcționat pentru mine
  • Aceasta este ‘ forța brută a tuturor soluțiilor de aici. : /

Răspuns

Dacă rulați bash cu -e va ieși în orice condiții de eroare:

#!/bin/bash -e false # returns 1 echo This won"t be printed 

Comentarii

  • Prima linie aici este de departe cea mai simplă soluție pentru un script banal pe care nu ‘ nu doriți să petreceți prea mult timp!

Răspundeți

De ce nu,

while [ 1 ]; do COMMAND || break; done; 

Sau când este utilizat într-un script,

#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done; 

Comentarii

  • Soluție foarte elegantă. Dar ‘ nu ar funcționa decât dacă COMMAND returnează întotdeauna o stare de ieșire de succes?
  • Da @howardh, că ‘ este corect.

Răspuns

  1. Puteți oricând oricând un proces folosind PID-ul său, acolo ” Nu este nevoie să vă închideți terminalul
  2. Dacă doriți să rulați ceva într-o buclă infinită ca un daemon, atunci cel mai bine îl veți pune în fundal
  3. while : va crea o buclă infinită și vă salvează scriind [ 1 ]

    while :; do COMMAND; done & 

Aceasta va imprima PID. Dacă părăsiți solicitarea utilizând ctrl+d, atunci lucrarea de fundal nu va fi renunțată și puteți ulterior să o eliminați de oriunde utilizând kill PID

Dacă pierdeți urma PID-ului, puteți utiliza pstree -pa $USER sau pgrep -fl ".*PROCESS.*" pentru a vă ajuta să îl găsiți

Răspuns

Prefer o altă soluție:

touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done 

În ordine pentru a ucide bucla, faceți doar:

rm .runcmd && kill `pidof COMMAND` 

Răspundeți

Ce funcționează rezonabil bine pentru mine este:

 while sleep 1; do COMMAND; done  

Acest lucru funcționează deoarece somnul 1 rămâne în jur pentru un în timp ce și dacă primește ctrl + c se întoarce cu non zero și bucla se va termina.

Comentarii

  • +1, timpul de repaus poate fi, de asemenea, redus la 0.5 sau 0.1: while sleep 0.1; do COMMAND; done

Răspuns

Use trap

 exit_() { exit } while true do echo "running.." trap exit_ int done  

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *