Bir while döngüsü askıya alındıktan sonra neden duruyor?


10

Neden bash kullanıldığında ve while döngüsü askıya alındığında, döngü devam ettikten sonra durur? Aşağıda kısa bir örnek.

$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+  Stopped                 sleep 1
$ fg
sleep 1
$

Sinyallere aşinayım ve sanırım bu, burada bash'ın doğal davranışı olabilir, ancak neden bu şekilde davrandığını daha iyi anlamak istiyorum.


çünkü bir kesinti işlemek zorunda ve bunu karşılığında doğru bir şekilde yansıtmak zorunda $?ve öyle truedeğil true. muhtemelen. bence.
mikeserv

1
Umarım bu yorum işaretlenmez, ancak sorunuzu Unix koan tarzı başka bir soru ile cevaplayacağım: "Bir öğrenci, askıya alındıktan sonra neden oyun alanında savaşmayı durduruyor?" Cevap şu ki, artık kavga etmeye başlayabileceği oyun alanında değil. Böylece, söz konusu davranış basitçe durdurulmuştur.
rubynorails

Komutu durdurursunuz, döngü bozulur. Sonra döngü değil, tek uyku 1 komutu devam.
123

Yanıtlar:


10

Bu, birkaç kabukta bir hata gibi görünüyor, ksh93 ve zsh ile beklendiği gibi çalışıyor .

Arka fon:

Çoğu mermi, ana kabuğun içindeki while döngüsünü çalıştırıyor gibi görünüyor ve

Bourne Shell , oturum açma dışı bir kabukla ^ Z yazarsanız tüm kabuğu askıya alır

bash yalnızca askıya alır sleepve sonra while döngüsünü yeni bir kabuk istemi yazdırmak lehine bırakır

dash bu komutu vazgeçilmez kılar

Ksh93 ile işler çok farklı çalışır:

Komut ilk kez başlatılırken ksh93 de aynısını yapar, ancak sleepksh93'teki bir buitin gibi ksh93 de while döngüsünün ana kabuktan ayrılmasına ve ^ Z yazdığınızda askıya almasına neden olan bir işleyiciye sahiptir.

Daha sonra ksh93 yazıyorsanız fg, döngüyü hala çalıştıran çatallı çocuk devam eder.

Bash ve ksh93'ten jobcontrol mesajlarını karşılaştırırken ana farkı görüyorsunuz:

bash raporları:

[1]+ Stopped sleep 1

ancak ksh93 raporları:

^Z[1] + Stopped while true; do echo .; sleep 1; done

zsh benzer davranır ksh93

Her iki kabukta, ^ Z yazmadığınız sürece tek bir işleminiz (ana kabuk) ve ^ Z yazdıktan sonra iki kabuk işleminiz olur.


gelmez dashaslında döngü sonlanana sinyali işleme kadar rüzgar? içinde [d]?ashkaynak kodu vardır bu makroları olan INTON ve INTOFF boyunca dağılmış ve bir süre, tipik olarak alınan sinyaller INTOFF halde çok işlenir (veya civarında) INTON . Her neyse, sadece merak ediyorum çünkü daha iyi bildiğini düşünüyorum - harika bir cevap. teşekkür ederim.
mikeserv

Nadiren çizgi kullanıyorum ve kısa süre önce bash, ksh93 ve Bourne Shell'imle performans karşılaştırmaları için getirdim ve derledim. Bu testleri yaparken, çizginin çoğunlukla hızlı göründüğünü keşfettim çünkü çok baytlı karakterler için destek içermiyor. Tek bir sleep 100askıya alınabilir ve devam ettirilebilir dash, bu nedenle bu komuttaki dashsorunları biliyor ve iş kontrolünü seçici olarak devre dışı bırakıyor gibi görünüyor .
schily

yani, testlerinizde, çok dashgövdeli işlemeyi bırakarak diğer kabuklardaki performansını eşitleyebildiniz mi? ve evet, dashiş kontrolünü destekliyor, ancak standart, etkileşimli bir kabuğun TSTP'yi yoksayması gerektiğini ve geçerli kabukta etkileşimli bir terminalde bir while döngüsü çalıştırmanın diğerlerinden daha az etkileşimli bir kabuk olmadığını söylüyor.
mikeserv

Bunu tam olarak test etmedim, ancak çizgi ksh93 veya Bourne Kabuğundan daha fazla sistem CPU zamanı tüketirken (esas olarak daha fazla çatal () çağrısı yayınladığından), daha az kullanıcı CPU zamanı kullandığını ve bunun benzer bir toplamla sonuçlandığını görebiliyordum. Bourne Shell versiyonumla karşılaştırıldığında CPU zamanı. Bourne Shell'de kullanıcı CPU süresini azaltmaya çalışırken, bu sürenin çoğunun çok baytlı dönüşümlerde harcandığını biliyorum.
schily

4

Bu konuda Bash'in ortak yazarlarından birini yazdım ve işte onun yanıtı:

Gerçekten bir hata değil, ama kesinlikle bir uyarı.

Buradaki fikir, kabuk komutlarından farklı bir ayrıntı birimi olan işlemleri askıya almanızdır. Bir işlem askıya alındığında, bir seçeneğe sahip olan kabuğa geri döner (sıfır olmayan bir durumla, diyelim ki, döngü testi olan bir işlemi durdurduğunuzda sonuçları olur): döngüden çıkabilir veya döngüye devam edebilir , durdurulan işlemi geride bırakıyor. Bash bir iş durduğunda döngülerden kurtulmayı seçer ve her zaman seçer. Döngüye devam etmek nadiren istediğiniz şeydir.

Diğer bazı mermiler, SIGTSTP nedeniyle bir işlem askıya alındığında kabuğun bir kopyasını çatal gibi işler yapar ve bu işlemi durdurur. Bash bunu hiç yapmadı - fayda varantlarından daha karmaşık görünüyor - ama birisi bu kodu bir yama olarak göndermek istiyorsa, değişiklikleri dahil etmeye bakarım.

Bu nedenle, herhangi biri bir yama göndermek istiyorsa, man sayfalarında bulunan e-posta adreslerini kullanın.

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.