Loputtoman silmukan lopettaminen

Minulla on komento, jonka haluan suorittaa uudelleen automaattisesti aina, kun se päättyy, joten suoritin jotain tällaista:

while [ 1 ]; do COMMAND; done; 

mutta jos en pysty ”t pysäyttämään silmukkaa Ctrl-c : llä, koska se vain tappaa COMMAND eikä koko silmukka.

Kuinka saavuttaisin jotain samanlaista, mutta jonka voin pysäyttää sulkematta päätelaitetta?

Kommentit

  • Jos minä ’ m bashissa, lopetan työn vain Ctrl-Z: llä ja sitten ” tapan% 1 ” tappaa se.
  • Odota vain … Linus lainasi sanomaa: ”Me kaikki tiedämme, että Linux on hieno … se tekee loputtomia silmukoita 5 sekunnissa. ” – niin todella … odota vielä muutama sekunti, sen pitäisi olla valmis.
  • @PaulCager toimi myös minulle! Miksi se toimii siellä, missä Ctrl-C ei?
  • @cirosantilli se tappaa ulomman työn (bash ” kääre ”). Joissakin tilanteissa se ei voittanut ’ t välittömästi tappaa esimerkiksi ” COMMAND ” , jos taustoit sen, se voi hiipiä elossa, vaikka sen ’ vanhempi olisi kuollut. Silmukka on kuitenkin kuollut, ja ’ on tärkeä osa.

Vastaa

Tarkista komennon poistumistila. Jos komento lopetettiin signaalilla, poistumistunnus on 128 + signaalin numero. GNU-verkkodokumentaatiosta bashille :

Shellin tarkoituksiin komento joka poistuu nollatasolla, on onnistunut. Poistumistila, joka ei ole nolla, tarkoittaa vikaa. Tätä näennäisesti intuitiivista järjestelmää käytetään, joten on yksi hyvin määritelty tapa osoittaa menestys ja useita tapoja osoittaa eri vikatilat. Kun komento päättyy kohtalokkaaseen signaaliin, jonka numero on N, Bash käyttää arvoa 128 + N poistumistilana.

POSIX määrittelee myös , että signaalilla päättyvän komennon arvo on suurempi kuin 128, mutta ei näytä määrittävän sen tarkkaa arvoa, kuten GNU:

Komennon poistumistila, joka päättyi, koska se vastaanotti signaalin, ilmoitetaan suuremmaksi kuin 128.

Jos esimerkiksi keskeytät komennon Control-C: llä, poistumiskoodi on 130, koska SIGINT on signaali 2 Unix-järjestelmissä. Joten:

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

kommentit

  • On syytä mainita, että tätä ei voida taata, monet sovellukset eivät tee tätä.
  • @Kyle Jones: voitko linkittää POSIX / GNU-asiakirjoihin, joissa se mainitaan?
  • @cirosantilli Valmis.
  • @ KyleJones kiitos! Edelleen käytännössä ei toimi COMMAND = paplay alert.ogg -palvelussa, ehkä siksi, että paplay käsittelee signaalia?
  • @cirosantilli Kyllä, että ’ s syy. Jos prosessi käsittelee signaalin ja lopettaa, ’ eroaa prosessista, jonka prosessin päättää käsittelemätön signaali.

Vastaa

Voit pysäyttää työn ja asettaa sen taustalle, kun se on käynnissä, käyttämällä ctrl + z . voi tappaa työpaikkasi:

$ kill %1 

Missä [1] on työpaikkasi numero.

Kommentit

  • Katso myös tämä vastaus selityksiä ja muuta.
  • Tämä suhteellisen uusi vastaus vain toimii. Tarvitsee olla myönsi äänestyksen. +1
  • Autoit minua paljon. Tätä olen etsinyt tästä kysymyksestä 🙂

Vastaa

Sanoisin, että saattaa olla parasta laittaa ääretön silmukka komentosarjaan ja käsitellä signaaleja siellä. Tässä ”. Olen varma, että haluat muuttaa sitä sopivaksi. Komentosarja käyttää trap kiinni ctrl c (tai SIGTERM), tappaa komennon (olen käyttänyt testinä sleep tässä testinä) ja poistuu.

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

Kommentit

  • Hienoa. Tässä ’ s kuinka käytin tätä vinkkiä käynnistämään netcat-kääre automaattisesti: trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
  • jos lisäät tämän trap -lähestymistavan samaan komentoon (bash) lopetettavan silmukan kanssa, käytä $$ $! sijaan (katso täältä )

vastaus

Pidän yleensä vain Ctrl-C -näppäintä alaspainettuna. Ennemmin tai myöhemmin se ”rekisteröidy COMMAND” ja lopettaa siten while -silmukan. Ehkä on olemassa parempi tapa.

Kommentit

  • Etkö tiedä miksi, mutta se epäonnistuu tietyille KOMANDOILLE, kuten paplay 1s-tiedostossa .
  • Se toimi minulle
  • Se ’ on kaikkien ratkaisujen raaka voima. : /

vastaus

Jos suoritat bashin -e se poistuu kaikista virhetiloista:

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

kommentit

  • Ensimmäinen rivi on ylivoimaisesti yksinkertaisin ratkaisu triviaalille käsikirjoitukselle, johon et ’ halua kuluttaa liikaa aikaa!

Vastaa

Miksi ei yksinkertaisesti,

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

Tai kun sitä käytetään komentosarjassa,

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

Kommentit

  • Erittäin tyylikäs ratkaisu. Mutta eikö ’ t toimisi vain, jos COMMAND palauttaa aina onnistumisen poistumistilan?
  • Kyllä @howardh, että ’ s oikein.

Vastaa

  1. Voit aina tappaa prosessin sen PID: n avulla. ” sinun ei tarvitse sulkea päätelaitettasi
  2. Jos haluat ajaa jotain äärettömässä silmukassa kuten daemon, sinun on parasta laittaa se taustalle
  3. luo ääretön silmukka ja säästää sinua kirjoittamalla [ 1 ]

    while :; do COMMAND; done & 

Tämä tulostaa PID-tunnuksen. Jos poistut kehotteesta käyttämällä ctrl+d, taustatyö ei lopu ja voit myöhemmin tappaa työn mistä tahansa käyttämällä kill PID

Jos kadotat PID-tunnuksesi, voit käyttää sitä pstree -pa $USER tai pgrep -fl ".*PROCESS.*" auttamaan sinua löytämään sen

Vastaa

Haluan mieluummin toisen ratkaisun:

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

Järjestyksessä tappaa silmukka, tee vain:

rm .runcmd && kill `pidof COMMAND` 

Vastaa

Mikä toimii järkevästi Minulle on:

 while sleep 1; do COMMAND; done  

Tämä toimii, koska nukkuminen 1 pysyy paikallaan kun taas ja jos se saa ctrl + c, se palaa muulla kuin nollalla ja silmukka päättyy.

Kommentit

  • +1, uniaika voi olla myös pienennetty arvoon 0.5 tai 0.1: while sleep 0.1; do COMMAND; done

vastaus

Käytä trap

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

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *