Végtelen ciklus megszüntetése

Van egy olyan parancsom, amelyet minden alkalommal, amikor leáll, szeretnék automatikusan futtatni, ezért valami hasonlót futtattam:

while [ 1 ]; do COMMAND; done; 

de ha nem tudom leállítani a ciklust a Ctrl-c gombbal, mivel az csak megöli COMMAND és nem a teljes ciklus.

Hogyan érhetnék el valami hasonlót, de amit le tudok állítani anélkül, hogy be kellene zárnom a terminált?

Megjegyzések

  • Ha ‘ m a bash-ban, akkor a Ctrl-Z billentyűkombinációval állítom le a munkát, majd div id = “8afb4ea65f”>

hogy megölje.

  • Csak várjon … Linus idézete szerint: “Mindannyian tudjuk, hogy a Linux nagyszerű … végtelen hurkokat csinál 5 másodperc alatt. ” – szóval tényleg … várjon még néhány másodpercet, és befejeződik.
  • A @PaulCager nekem is működött! Miért működik ott, ahol a Ctrl-C nem?
  • @cirosantilli megöli a külső munkát (a bash ” burkoló “). Bizonyos helyzetekben ‘ t nem azonnal megöli például a ” COMMAND ” parancsot , ha háttérbe állítja, akkor még életben is elbújhat, ha ‘ szülője halott. De a hurok halott, és ez ‘ s a fontos részt.
  • Válasz

    Ellenőrizze a parancs kilépési állapotát. Ha a parancsot jelzéssel fejezték be, a kilépési kód 128 + a jel száma lesz. A GNU online dokumentációja a bash számára:

    A shell céljaira egy parancs amely kilép a nulla kilépési státusszal, sikerült. A nullától eltérő kilépési állapot hibát jelez. Ezt a látszólag ellentétes sémát alkalmazzák, így van egy jól körülhatárolható módszer a siker jelzésére, és sokféle módon lehet jelezni a különféle hibamódokat. Amikor egy parancs véget vet egy N jelű fatális jelnek, Bash a 128 + N értéket használja kilépési állapotként.

    A POSIX azt is megadja , hogy a jel által végződött parancs értéke nagyobb, mint 128, de úgy tűnik, hogy nem adja meg annak pontos értékét, mint a GNU:

    Egy olyan parancs kilépési állapotát, amely azért szűnt meg, mert jelet kapott, nagyobbnak kell jelenteni, mint 128.

    Ha például megszakít egy parancsot a C-vezérlővel, a kilépési kód 130 lesz, mert a SIGINT a 2. jel a Unix rendszereken. Tehát:

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

    megjegyzések

    • Meg kell említeni, hogy ez valójában nem garantált, sok alkalmazás nem fogja ezt megcsinálni.
    • @ Kyle Jones: tud-e linkelni a POSIX / GNU dokumentumokba, amelyek ezt megemlítik?
    • @cirosantilli Kész.
    • @ KyleJones köszönöm! A gyakorlatban még mindig nem működik a COMMAND = paplay alert.ogg, talán azért, mert a paplay kezeli a jelet?
    • @cirosantilli Igen, hogy ‘ s az oka. Ha egy folyamat kezeli a jelet, és kilép, akkor az ‘ különbözik attól a folyamattól, amelyet egy kezeletlen jel zár le.

    Válasz

    A ctrl + z használatával leállíthatja és háttérbe helyezheti a munkáját, miközben fut. megöli a munkáját a következővel:

    $ kill %1 

    Ahol [1] a munkája száma.

    Megjegyzések

    • Lásd még ezt a választ a magyarázatokért és egyebekért.
    • Ez a viszonylag friss válasz egyszerűen működik. Meg kell szavazott. +1
    • Nagyon sokat segítettél nekem. Ezt kerestem ebben a kérdésben 🙂

    Válasz

    Azt mondanám, hogy az lenne a legjobb, ha a végtelen ciklusát egy szkriptbe tennénk, és ott kezelnénk a jeleket. Biztos vagyok benne, hogy módosítani akarja, hogy megfeleljen. A szkript a trap segítségével elkapja a ctrl c (vagy a SIGTERM) fájlokat, megöli a parancsot (sleep -t használtam tesztként) és kilép.

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

    Megjegyzések

    • Szép. Itt ‘ s hogyan használtam ezt a tippet egy automatikus újraindítású netcat csomagoló készítéséhez: trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
    • ha ezt a trap megközelítést hozzáadja ugyanahhoz a (bash) szkripthez, a megölendő végtelen hurkot használva, használja a $$ $! helyett (lásd itt )

    Válasz

    Általában csak lenyomva tartom a Ctrl-C gombot. Előbb vagy utóbb “regisztrál a ” s így megszakítja a while ciklust. Talán van ennél jobb módszer is.

    Megjegyzések

    • Nem tudom, miért, de nem sikerül bizonyos COMMAND-oknál, például paplay egy 1-es fájlnál .
    • Nekem bevált
    • Ez ‘ az itteni megoldások nyers erejét. : /

    Válasz

    Ha a bash-t futtatja a -e minden hiba esetén kilép:

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

    Megjegyzések

    • Az első sor itt messze van a legegyszerűbb megoldás egy triviális szkriptre, amelyre nem kíván ‘ túl sok időt tölteni!

    Válasz

    Miért nem egyszerűen,

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

    Vagy ha szkriptben használják,

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

    Megjegyzések

    • Nagyon elegáns megoldás. De vajon ‘ ez csak akkor működne, ha a COMMAND mindig sikeres kilépési állapotot adna vissza?
    • Igen @howardh, hogy ‘ s helyesek.

    Válasz

    1. Egy folyamatot mindig meg lehet ölni annak PID-jével, ott ” nincs szükség a terminál bezárására.
    2. Ha egy végtelen ciklusban szeretne futtatni valamit, mint egy démon, akkor a legjobban a háttérbe helyezheti
    3. while : végtelen ciklust hoz létre, és elmenti a [ 1 ]

      while :; do COMMAND; done & 

    Ez kinyomtatja a PID-t. Ha kilép a parancssorból az ctrl+d használatával, a háttérmunka nem zárul le, és később bárhonnan megölheti a munkát a kill PID

    Ha elvesztette a PID azonosítóját, a pstree -pa $USER vagy a pgrep -fl ".*PROCESS.*" használatával megkeresheti

    Válasz

    Egy másik megoldást preferálok:

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

    Sorrendben a hurok elpusztításához tedd:

    rm .runcmd && kill `pidof COMMAND` 

    Válasz

    Mi működik ésszerűen nekem jó:

     while sleep 1; do COMMAND; done  

    Ez azért működik, mert az 1. alvás egy míg és ha a ctrl + c értéket kapja, akkor nem nullával tér vissza, és a hurok véget ér.

    Megjegyzések

    • +1, az alvási idő is megadható 0.5 vagy 0.1 -re redukálva: while sleep 0.1; do COMMAND; done

    Válasz

    A trap használata –

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

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük