Sonsuz bir döngüyü sonlandırma


52

Her sonlandırıldığında otomatik olarak tekrar çalıştırmak istediğim bir emir var, bu yüzden şöyle bir şey yaptım:

while [ 1 ]; do COMMAND; done;

ancak bu döngüyü durduramazsam , tüm döngüyü değil, Ctrl-csadece öldürür COMMAND.

Benzer bir şeyi nasıl elde edebilirim ama terminali kapatmak zorunda kalmadan hangisini durdurabilirim?


11
Eğer bash içindeysem, işi durdurmak için sadece Ctrl-Z kullanın ve sonra onu öldürmek için "% 1" i öldür.
Paul Cager

3
Sadece bekleyin ... Linus, “Hepimiz Linux'un harika olduğunu biliyoruz… 5 saniyede sonsuz döngüler yapıyor” diyordu . - yani gerçekten ... sadece birkaç saniye bekleyin, tamamlaması gerekiyor.
lornix

@ PaulCager de benim için çalıştı! Neden Ctrl-C'nin çalışmadığı yerlerde çalışıyor?
Ciro Santilli,

@cirosantilli dış işi öldürür (bash "sarmalayıcı"). Bazı durumlarda, hemen "KOMUTANLIĞI" öldürmez, örneğin, eğer arka plan yaparsanız, ebeveyni ölmüş olsa bile, canlı olarak gizlice geçebilir. Ancak döngü öldü ve önemli olan bu.
orion

Yanıtlar:


37

Komutun çıkış durumunu kontrol edin. Komut bir sinyal ile sonlandırıldıysa, çıkış kodu 128 + sinyal numarası olacaktır. Bash için GNU çevrimiçi belgelerinde :

Kabuğun amaçları doğrultusunda, sıfır çıkış durumuyla çıkan bir komut başarılı oldu. Sıfır olmayan bir çıkış durumu başarısızlığı gösterir. Bu görünüşte karşı sezgisel şema kullanılır, bu nedenle başarıyı belirtmek için iyi tanımlanmış bir yol ve çeşitli başarısızlık modlarını belirtmek için çeşitli yollar vardır. Bir komut, sayısı N olan ölümcül bir sinyalde sonlandığında, Bash, çıkış durumu olarak 128 + N değerini kullanır.

POSIX ayrıca , bir sinyal tarafından sonlandırılan bir komutun değerinin 128'den büyük olduğunu ancak GNU gibi yaptığı gibi tam değerini belirlemediğini belirtir:

Sinyal aldığı için sonlandırılan bir komutun çıkış durumu 128'den büyük olarak bildirilmelidir.

Örneğin, C komutunu bir komutu keserseniz, çıkış kodu 130 olur çünkü SIGINT Unix sistemlerinde 2 numaralı sinyaldir. Yani:

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

9
Bunun garanti edilmediğinden bahsedilmelidir, aslında birçok uygulama bunu yapmayacaktır.
Chris Down,

1
@Kyle Jones: Bundan bahseden POSIX / GNU belgelerine bağlanabilir misiniz?
Ciro Santilli,

@cirosantilli Tamam.
Kyle Jones

@KyleJones teşekkürler! Hala pratikte COMMAND için çalışmıyor = paplay alert.ogg, belki de paplaysinyal işlediğinden?
Ciro Santilli,

@cirosantilli Evet, nedeni bu. Bir işlem sinyali ele alır ve çıkarsa, işlenmeyen bir sinyal tarafından sonlandırılan işlemden farklıdır.
Kyle Jones

48

ctrl+ Tuşlarını kullanırken işinizi durdurabilir ve işinizi arka planda tutabilirsiniz z. O zaman işini şununla öldürebilirsin:

$ kill %1

İş numaranız [1].


Açıklamalar ve daha fazlası için ayrıca bu cevaba bakınız .
Skippy le Grand Gourou,

2
Bu nispeten yeni cevap sadece işe yarıyor. Alınması gerekiyor. +1
shivams

Bana çok yardım ettin. Bu soruda
Maximilian Ruta

18

Sonsuz döngünüzü bir betiğe koymanız ve oradaki sinyalleri işlemenin en iyi olabileceğini söyleyebilirim. İşte temel bir başlangıç ​​noktası . Eminim buna göre değiştirmek isteyeceksiniz. Komut kullanır trapyakalamak için ctrl- c(veya SIGTERM), komutu (ben kullandım kapalı öldüren sleepbir test olarak burada) ve çıkışları.

cleanup ()
{
kill -s SIGTERM $!
exit 0
}

trap cleanup SIGINT SIGTERM

while [ 1 ]
do
    sleep 60 &
    wait $!
done

4
Güzel. İşte bu bahşişi nasıl otomatik bir sarmalayıcı yapmak için kullanmıştım:trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
Douglas

2
bu trapyaklaşımı öldürülecek sonsuz döngü ile aynı (bash) betiğine eklerseniz , $$bunun yerine kullanın $!( buraya bakın )
ardnew

15

Genelde sadece basılı tutarım Ctrl-C. Er ya da geç s'lerin arasında kaydolacak COMMANDve böylece whiledöngüyü sona erdirecektir . Belki daha iyi bir yol vardır.


1
Neden olduğundan emin değilim, ancak paplaybir 1s dosyasındaki gibi bazı KOMUTLAR için başarısız .
Ciro Santilli,

Benim için çalıştı
alexandr

Buradaki tüm çözümlerin kaba kuvveti. : /
markroxor


7

Neden basit değil

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

Veya bir komut dosyasında kullanıldığında,

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

1
Çok şık bir çözüm. Ancak bu yalnızca COMMAND her zaman başarılı bir çıkış durumu döndürürse işe yaramaz mı?
15'te

Evet @ howardh, bu doğru.
Dale Anderson,

3

Başka bir çözümü tercih ederim:

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

Döngüyü öldürmek için, sadece yapın:

rm .runcmd && kill `pidof COMMAND`

2
  1. PID'yi kullanarak bir işlemi her zaman öldürebilirsiniz, terminalinizi kapatmaya gerek yoktur
  2. Daemon gibi sonsuz bir döngüde bir şey çalıştırmak istiyorsanız, o zaman en iyisi arka planda koymak
  3. while : Sonsuz bir döngü oluşturacak ve sizi [ 1 ]

    while :; do COMMAND; done &

Bu PID'yi basacaktır. Kullanarak isteminizden ctrl+dçıkarsanız, arka plan işi sona ermeyecek ve daha sonra kullanarak herhangi bir yerden işi öldürebilirsiniz.kill PID

PID’nizin kaydını kaybederseniz, onu bulmanıza yardımcı olmak için kullanabilir pstree -pa $USERveya kullanabilirsiniz pgrep -fl '.*PROCESS.*'.


0

Kullan trap-

exit_()
{
    exit
}

while true
do
    echo 'running..'
    trap exit_ int
done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.