Ne oluyor
Ctrl+ Tuşuna bastığınızda C, SIGINT
sinyal tüm ön plan işlem grubuna iletilir . Burada hem find
işleme hem de çağrılan kabuk işlemine gönderilir. find
hemen çıkarak tepki verir ve kabuk tuzağı çağırarak tepki verir.
Tuzaktaki kod geri dönerse (yani çağrı yapmazsa exit
), yürütme, sinyal tarafından kesilen komuttan sonraki komutla devam eder. Burada, find
komut betiğin sonuna geldikten sonra, komut dosyası hemen yine de çıkar. Ancak başka bir komut ekleyerek 0 ile 1 girme arasındaki farkı görebilirsiniz:
find /
echo "find returned $?"
İstediğinizi yapmanın bir yolu (ama muhtemelen yapmamalısınız)
Ne istersen yapabilirsin; ama cevabımın bu kısmı, gerçek bir problemi çözmek yerine kabuk programlamayı keşfetmekle ilgili.
- Bir tasarım meselesi olarak, yeniden başlatılabilir bir sinyal normalde kabuk betiklerinin olduğu nispeten basit programlarda normalde beklediğiniz şey değildir. Beklenti, Ctrl+ ' Cnın senaryoyu öldürmesi.
- Aşağıda göreceğiniz gibi, kabuğun yeteneklerini biraz daha genişletiyor.
Eğer öldürme kaçınmak istiyorsanız find
, size bunu başlatmak için gereken arka plan : find / &
. Ardından normalden çıkmasını beklemek için wait
yerleşkeyi kullanın. Bir sinyal, wait
yaymak istediğiniz sinyali alana kadar bir döngüde çalıştırabileceğiniz yerleşik kesintiye neden olur. Sonra kill
işi öldürmek için kullanın .
hell () {
echo "Do you want to quit? Press 1 for yes and 0 for no"
read n
if [ "$n" = 1 ]; then
# Kill the job if it's running, then exit
if [ -n "$job_pid" ]; then kill $job_pid; fi
exit 1
fi
}
job_pid=
trap "hell" SIGINT
# Start a demo job in the background
for i in 1 2 3 4 5; do date; sleep 1; done &
job_pid=$!
# Call wait in a loop; wait will return 0 if the job exits, and 128+$signum if interrupted by a signal.
while ! wait; do
echo "resuming wait"
done
job_pid=
echo last exit code: $?
Kabukta bu yaklaşımın sınırlamaları vardır:
- Bir yarış koşulu var: iş bittikten hemen sonra Ctrl+ çizgisine basmadan + tuşuna basarsanız , sinyal işleyici öldürmeye çalışacak , ancak işlem artık mevcut değil (bir zombi olarak bile , zaten hasat ettiğinden) ve süreç Kimlik başka bir işlem tarafından yeniden kullanılmış olabilir. Bu, kabukta kolayca düzeltilemez (belki bir işleyici ayarlayarak ?).C
job_pid=
$jobpid
wait
SIGCHLD
- İşten iade durumuna ihtiyacınız varsa,
wait $job_pid
formu kullanmanız gerekir . Ama o zaman “ wait
bir sinyalle kesildi” yi “iş bir sinyalle öldürüldü” (ne de “kendi statüsüyle geri dönüş durumu ≥128” ile bitirilen işten) ayırt edemezsiniz, ama bu kabukta genel bir gerçektir programlama).
- Bu, eğer birden fazla subjobs'a kolayca uzanmayacaktır. Çoğu kabuk uygulamasında temellerin ötesine geçtiğinizde tuzakların ve sinyallerin davranışının genellikle şaşırtıcı olduğunu unutmayın (sadece ksh bunu iyi yapar).
Bu sınırlamaların üstesinden gelmek için Perl veya Python gibi meraklı bir dil kullanın.