Bash'da iki eşzamanlı komutla Ctrl-C


15

Bir Linux makinesinde bash'da iki komutu aynı anda çalıştırmak istiyorum. Bu ./execute.shyüzden bash senaryomda şunu koydum:

command 1 & command 2
echo "done"

Ancak bash betiğini durdurmak ve Ctrl+ düğmesine basmak istediğimde C, yalnızca ikinci komut durdurulur. İlk komut çalışmaya devam eder. Tüm bash betiğinin durdurulduğundan nasıl emin olabilirim? Veya her iki komutu da nasıl durdurabilirim? Çünkü bu durumda Ctrl+ ne sıklıkla bastığım önemli değil C, komut çalışmaya devam ediyor ve terminali kapatmak zorunda kalıyorum.


Takip sorusunu ayrı bir soruya dönüştürün ve buradan kaldırın. Şimdi bir ziyaretçi için her iki sorunun cevaplanıp cevaplanmadığı ya da sadece başlangıç ​​sorusu belirsizdir.
Zelda

Yanıtlar:


17

Yazarsanız

command 1 & command 2

bu eşittir

command 1 &
command 2

yani bu, ilk komutu arka planda çalıştırır ve ardından ikinci komutu ön planda çalıştırır. Özellikle bu , hala çalışıyor olsa bile bittikten echo "done"sonra yazdırdığınız anlamına gelir .command 2command 1

Muhtemelen istiyorsun

command 1 &
command 2 &
wait
echo "done"

Bu, her iki komutu da arka planda çalıştırır ve her ikisinin de tamamlanmasını bekler.


CTRL-C tuşlarına basarsanız, bu sadece SIGINT sinyalini ön plan işlemine, yani command 2sürümünüzde veya sürümümde gönderir wait.

Böyle bir tuzak kurmayı öneririm:

#!/bin/bash

trap killgroup SIGINT

killgroup(){
  echo killing...
  kill 0
}

loop(){
  echo $1
  sleep $1
  loop $1
}

loop 1 &
loop 2 &
wait

Tuzak ile CTRL-C tarafından üretilen SIGINT sinyali yakalanır ve yerine killgrouptüm bu işlemleri öldüren fonksiyon gelir.


Cevabınız için teşekkür ederim! Ancak takip eden bir sorum var. Şimdi aşağıdaki komut dosyası var: tuzak killgroup SIGINT killgroup () {echo killing ... kill 0} command001 command1 & command2 command2 bittiğinde komut dosyası devam etmesine izin verildi çünkü wait komutu ommitted. Ancak komut dosyasını çalıştırdığımda komut 1 zaten başlamış gibi görünüyor. Bunu düzeltebilir miyim? Teşekkürler
maero21

command1, command001 bittikten hemen sonra başlar. set -xçalıştırılan komutları yazdırmak için komut dosyanızın başında kullanabilirsiniz .
michas

6

Bir komut dosyasından arka plana bir komut koyarken, PID ekranda görüntülenmez. $!Komut1'in PID'sini yakalamak için son işlemin PID'sini saklayan yerleşik değişkeni kullanabilirsiniz .

command1 &
echo $!

komut1'in PID'sini yankılandıracaktı.

Bash ayrıca, belirli sinyaller alındığında çalıştırmak için bir dizi komutu kaydetmek için kullanabileceğiniz tuzak yerleşimini de sağlar. Bunu ana komut dosyasından çıkmadan önce SIGINT ve kill command1'i yakalamak için kullanabilirsiniz.

#!/bin/bash

onINT() {
echo "Killing command1 $command1PID too"
kill -INT "$command1PID"
exit
}

trap "onINT" SIGINT
command1 &
command1PID="$!"
comamnd2
echo Done

Şimdi, komut 2 çalışırken vurmak Ctrl Chem komut1'in hem de komut2'nin SIGINT'e gönderilmesine neden olacaktır.


%nBu kabuktaki belirli arka plan işlerini öldürmek için de sözdizimini kullanabilirsiniz . Genellikle kill %1en son ve tek arka plan işlemini öldürmek için sorun yaşarsınız. Daha fazla arka plan işlemiyle, jobsönce listeyi görmek için düğmelerini kullanın .
9000

@ 9000: Evet ama OP komutlarını bir komut dosyasında (./execute.sh) çalıştırıyor, bu yüzden işleri işe almak çok daha sorunlu mu?

@lain: kesinlikle. Bir senaryodan kaçmakla ilgili noktayı kaçırdım.
9000

5

GNU Parallel'ın daha yeni sürümleri istediğinizi yapacak:

parallel ::: "command 1" "command 2"
echo "done"

Veya commandaynı kalırsa:

parallel command ::: 1 2
echo done

Hızlı bir giriş için giriş videosunu izleyin: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Eğiticiyi gözden geçirin (man parallel_tutorial). Bunun için seni sevgiyle komut satırı.


1

Ctrl+ Cön işleminize bir SIGINT sinyali gönderir command2. command1arka planda çalıştırılır, bu nedenle giriş akışı tarafından ilgilenilmez.

Yazdığınızda command1 &, bash size 'PID' sürecini vermelidir [1234]. Bu işlemi öldürmek için kullanabilirsiniz kill 1234. Şimdi, her ikisinin PID'lerine sahipseniz command1ve command2(bir göz atın ps -ef), killhepsini sonlandırmak için kullanabilirsiniz :

kill pid1 pid2 pid3 ...

Biraz hile, her iki komutu da arka planda çalıştırmaktır:

command1 & command2 &

Bash size her iki PID'yi de öldürecek. Başka bir numara, command1öldürdüğünüzde ön plana geri dönmek olacaktır command2:

command1 & command2
# Hit Ctrl+C : command2 terminates.

fg # Bring back command1 to foreground.
# Hit Ctrl+C again, command1 terminates.

Daha fazla bilgiye buradan ulaşabilirsiniz: http://linuxg.net/how-to-manage-background-and-foreground-processes/

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.