Birden çok komut çalıştırın ve bunları bash'te birer olarak öldürün


51

Tek bir kabuk üzerinde birden fazla komut (işlem) çalıştırmak istiyorum. Hepsinin kendi sürekli çıktısı var ve durmuyor. Onları arka planda çalışan sonları Ctrl- C. Tek bir süreç olarak çalıştırmak istiyorum ile hepsini durdurmaya muktedir (belki, altkabuk?) Ctrl- C.

Özel olarak, birim testlerini mocha(izleme modu), sunucuyu ve bazı dosya ön işleme (izleme modlarını) ile çalıştırmak ve her birinin çıktısını bir terminal penceresinde görmek istiyorum. Temelde bazı görev koşucu kullanmaktan kaçınmak istiyorum.

İşlemleri arka planda ( &) çalıştırarak gerçekleştirebilirim , ancak daha sonra onları durdurmak için ön plana koymak zorundayım. Onları sarmak için bir süreç istiyorum ve bu süreci durdurduğumda 'çocuklarını' durduruyor.


Aynı anda mı yoksa birbiri ardına mı koşmalılar?
Minix

Evet, süreçler eşzamanlı olarak çalışmalı, fakat her birinin çıktısını görmem gerekiyor.
user1876909 20:15

Yanıtlar:


67

Komutları aynı anda çalıştırmak için &komut ayırıcıyı kullanabilirsiniz .

~$ command1 & command2 & command3

Bu başlar command1, sonra arka planda çalışır. İle aynı command2. Sonra command3normal şekilde başlar .

Tüm komutların çıktısı bir araya toplanacak, ancak bu sizin için bir sorun değilse, çözüm bu olacaktır.

Daha sonra çıktıya ayrı bir göz atmak isterseniz, her komutun teeçıktısını, çıktıyı yansıtmak üzere bir dosya belirtmenize izin veren şekilde yönlendirebilirsiniz.

~$ command1 | tee 1.log & command2 | tee 2.log & command3 | tee 3.log

Çıktı muhtemelen çok karışık olacak. Buna karşı koymak için, her komutun çıktısını kullanarak bir önek verebilirsiniz sed.

~$ echo 'Output of command 1' | sed -e 's/^/[Command1] /' 
[Command1] Output of command 1

Öyleyse hepsini bir araya getirirsek, şunları elde ederiz:

~$ command1 | tee 1.log | sed -e 's/^/[Command1] /' & command2 | tee 2.log | sed -e 's/^/[Command2] /' & command3 | tee 3.log | sed -e 's/^/[Command3] /'
[Command1] Starting command1
[Command2] Starting command2
[Command1] Finished
[Command3] Starting command3

Bu, muhtemelen göreceğiniz şeyin oldukça idealize edilmiş bir versiyonudur. Ama şu anda düşünebildiğim en iyisi bu.

Hepsini bir kerede durdurmak istiyorsanız, yerleşimi kullanabilirsiniz trap.

~$ trap 'kill %1; kill %2' SIGINT
~$ command1 & command2 & command3

Bu çalıştırır command1ve command2arka planda ve command3sen onu öldürmek sağlayan ön planda, içinde Ctrl+ C.

Eğer geçen süreci öldürdüğünüzde Ctrl+ biz interupt sinyali basarak gönderilen şeyin alımı ile çalıştırılmaya bağlı çünkü komutlar, yürütür + .Ckill %1; kill %2CtrlC

Sırasıyla 1. ve 2. arka plan sürecini öldürür (siz command1ve command2). Komutlarını kullanmayı unutma, komutlarını kullanman bittikten sonra trap - SIGINT.

Komutun tam canavarı:

~$ trap 'kill %1; kill %2' SIGINT
~$ command1 | tee 1.log | sed -e 's/^/[Command1] /' & command2 | tee 2.log | sed -e 's/^/[Command2] /' & command3 | tee 3.log | sed -e 's/^/[Command3] /'

Elbette ekrana bir göz atabilirsiniz . Konsolunuzu istediğiniz kadar ayrı konsollara bölmenizi sağlar. Böylece tüm komutları ayrı ayrı izleyebilirsiniz, ancak aynı anda.


3
Tüm eleştiriyi bekliyorum. :)
Minix

2
Teşekkür ederim. Tam olarak istediğimi yapar (tuzak komutu). Çözüm, yine de, yeniden kullanılabilirlik için bir senaryoya sarılmalıdır.
user1876909

@ user1876909 İşte bir iskelet. Detaylar size kalmış [1]. Yardımcı olduğuma sevindim. [1] pastebin.com/jKhtwF40
Minix

3
bu oldukça zekice bir çözüm, iv yeni bir şey öğrendi, bravo +1
mike-m

1
Bu harika. Kazacak ve bu cevaptan öğreneceğim çok şey var.
ccnokes

20

Aynı süreç grubunda onları (ve yalnızca onları) çalıştırmayı düzenlerseniz, bir grup işlemi bir kerede kolayca öldürebilirsiniz .

Linux, setsidbir programı yeni bir süreç grubunda (yeni bir oturumda, hatta bunu umursamıyoruz) çalıştırmak için yardımcı program sağlar. (Bu yapılabilir ama daha karmaşık olmadan setsid.)

Bir işlem grubunun işlem grubu kimliği (PGID), gruptaki orijinal üst işlemin işlem kimliğidir. Bir işlem grubundaki tüm işlemleri öldürmek için, PGID'nin negatifini killsistem çağrısına veya komutuna iletin . PGID, bu PID ile orijinal süreç ölse bile (biraz kafa karıştırıcı olsa da) geçerli kalır.

setsid sh -c 'command1 & command2 & command3' &
pgid=$!
echo "Background tasks are running in process group $pgid, kill with kill -TERM -$pgid"

İşlemleri arka planda etkileşimli olmayan bir kabuktan çalıştırırsanız, hepsi kabuğun işlem grubunda kalır. Yalnızca arka plan işlemlerinin kendi işlem gruplarında yürüdüğü etkileşimli kabuklarda. Bu nedenle, komutları ön planda kalan etkileşimli olmayan bir kabuktan atarsanız, Ctrl+ Chepsini öldürür. waitKabuğun tüm komutların çıkmasını beklemesini sağlamak için yerleşimi kullanın .

sh -c 'command1 & command2 & command3 & wait'
# Press Ctrl+C to kill them all

2
tanımsız cevap (alttaki yöntem). Anlaması ve ezberlemesi basit.
Nicolas Marshall

14

Bunun henüz burada olmadığına şaşırdım, ama bunu yapmanın en sevdiğim yolu arka plan komutlarıyla alt kabuk kullanmak . Kullanımı:

(command1 & command2 & command3)

Çıktı, her ikisinden de görülebilir, tüm bash komutları ve kolaylıkları hala mevcuttur ve bir Ctrl-ctanesi hepsini öldürür. Bunu genellikle canlı hata ayıklama istemcisi dosya sunucusunu ve arka uç sunucusunu aynı anda başlatmak için kullanırım, böylece istediğim zaman ikisini de kolayca öldürebilirim.

Bu çalışma şekli olmasıdır command1ve command2yeni altkabuk örneğinin arka planda çalışan ve command3bu örneğinin ön planda olduğu ve altkabuk öncelikle gelen öldürmek sinyal alır budur Ctrl-cTuşa. Bu, kimin hangi sürecin sahibi olduğuna ve arka plan programlarının ne zaman öldürüleceğine ilişkin bir bash betiği çalıştırmaya çok benzer.


waitSon komut olarak eklerseniz (örneğin komut3), kullanıcı Ctrl-c tuşlarına bastıktan sonra temizleme kodunu çalıştırabilirsiniz .
dotnetCarpenter

0

Noktalı virgül kullanabilir ;veya bunun &&gibi:

cmd1; cmd2   # Runs both the commands, even if the first one exits with a non-zero status.

cmd1 && cmd2 # Only runs the second command if the first one was successful.

Bu aynı anda komutları çalıştırmaz.
Gilles 'SO- kötülük'

-2

Kullanabilirsiniz pipe. Bu, borunun her iki ucundaki komutları aynı anda başlatacaktır. Siz de tüm komutları durdurabilmelisiniz CTRL-C.

1st command | 2nd command | 3rd command

Komutları birbiri ardına çalıştırmak isterseniz, @ serenesat metodunu kullanabilirsiniz.


Bu, ilk komutun çıktısını, ikincisine (vb.) Geçirir; bu, ilk komutun çıktısının terminalde bitmesi gerektiği için burada uygun değildir.
Gilles 'SO- kötülük'
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.