Birden fazla bash komut dosyasını çağırmak ve bunları paralel olarak çalıştırmak, sırayla değil


19

: Ben bash komut dosyaları üç (veya daha fazla) olduğunu varsayalım script1.sh, script2.shve script3.sh. Bu senaryoların üçünü de çağırmak ve paralel olarak çalıştırmak istiyorum . Bunu yapmanın bir yolu sadece aşağıdaki komutları yürütmektir:

nohup bash script1.sh &
nohup bash script2.sh &
nohup bash script3.sh &

(Genel olarak, komut dosyalarının tamamlanması birkaç saat veya gün sürebilir, bu nohupnedenle konsolum kapansa bile çalışmaya devam etmek için kullanmak istiyorum .)

Ancak, bu üç komutu tek bir çağrı ile paralel olarak yürütmenin herhangi bir yolu var mı?

Şöyle bir şey düşünüyordum

nohup bash script{1..3}.sh &

ancak bu yürütmeye görünür script1.sh, script2.shve script3.shdeğil paralel olarak, sırayla.


2
"Tek arama" ne anlama geliyor?
jw013

1
Kullanım durumu nedir? Başlamak için bir milyon komut dosyanız var mı?
l0b0

@ jw013 Yani, tek bir kısa satır komutu gibi bir şey. Başlamak için 100 komut dosyam varsa , 100 farklı kez yazmak yerine kısa ( nohup bash script{1..100}.sh &veya gibi for i in {1..100}; do nohup bash script{1..100} &; done) bir şey yazabilmek istiyorum nohup bash script*.sh &.
Andrew

1
Komut dosyalarının yararlı çıktısı olması durumunda: Konsol sorununu çözmek için çıktıya (ve girişe) devam etmek için bunları screenda (veya tmux) içinde başlatabilirsiniz .
Hauke ​​Laging

1
Bu komutların 3 tanesini aynı satıra yazmanızı engelleyen hiçbir şey yoktur. nohup ... & nohup ... & nohup ... &. Bunun yerine, her komut dosyasının adını tek tek yazmadan tüm komut dosyalarını çalıştırmak istediğinizi kastediyorsanız, basit bir döngü bunu yapar.
jw013

Yanıtlar:



14

Daha iyi bir yol GNU Parallel kullanmak olacaktır . GNU paralel basittir ve bununla paralel olarak çalışacak işlerin sayısını işler üzerinde daha fazla kontrol ile kontrol edebiliriz.

Aşağıdaki komutta script{1..3}.shgenişletilir ve bashparalel olarak argümanlar olarak gönderilir . Burada -j0mümkün olduğu kadar çok işin yapılması gerektiğini gösterir. Varsayılan parallelolarak bir cpu çekirdeği için bir iş çalıştırır.

$ parallel -j0 bash :::: <(ls script{1..3}.sh)

Ayrıca şunu kullanmayı da deneyebilirsiniz:

$ parallel -j0 bash ::: script{1..3}.sh

Herhangi bir hata mesajı alırsanız ikinci yöntemi uygularken, bu --tollefseçenek ayarlanmış demektir /etc/parallel/configve silinmesi gerekir ve her şey iyi çalışır.

Daha zengin seçenekler için GNU Parallelsman sayfasını buradan okuyabilirsiniz .

Ve işleri uzak bir makineden çalıştırıyorsanız, screenağ sorunları nedeniyle oturumun kapanmaması için daha iyi kullanın . nohupile geldiğinin Bash son sürümleri gibi, gerekli değildir huponexitolarak offve bu göndermesini üst kabuğunu önleyecektir HUPonun çıkışında sırasında çocuklara sinyali. Eğer ayarlanmamışsa

$ shopt -u huponexit  

bashKabuk olarak kullanılacaksa , parallel -j0 bash :::: <(ls script{1..3}.sh)azaltılabilir parallel -j0 bash :::: script{1..3}.shmi?
iruvar

Hayır, '::::' paralel olarak kullanıldığında, argümanın komutun kendisini değil, yürütülecek komutları içeren bir dosya olduğu anlamına gelir. Burada, bir dosya tanımlayıcı içindeki komut dosyası adlarını yeniden yönlendirmek için işlem ikamesi kullanıyoruz.
Kannan Mohan

Ee ... bu durumda neden olmasın parallel -j0 bash ::: script{1..3}.sh?
iruvar

O ediyor bash ::: script{1..3}.shgeçirilmeden paralleldeğil ::: script{1..3}.sh. Bu birinci genişletmek gerektiğini Yani parallel bash ::: script1.sh script2.sh script3.shkabuk ve o zamana parallelhalinin çağrıları bash script1.sh, bash script2.sh, bash script3.sh. Denedim
iruvar

1
Hayır, kafam karışmadı, tüm belirttiğim, OP'nin probleminin daha iyi çözülmesidir parallel -j0 bash ::: script{1..3}.sh- bu, ::::işlem ikamesi ihtiyacını ortadan kaldırdığı için yaklaşımdan daha iyidir . Ayrıca ls çıktı ayrıştırma tuzakları ile basmış
iruvar

9

xargsParalel olarak birden fazla komut dosyası çalıştırmak için de kullanabiliriz .

$ ls script{1..5}.sh|xargs -n 1 -P 0 bash

burada her komut dosyası bash'a bağımsız değişken olarak geçirilir. -P 0paralel işlem sayısının olabildiğince fazla olabileceğini gösterir. Ayrıca bash varsayılanı kullanmak daha güvenlidir job control feature (&).


5

Tek hatlı bir çözüm:

$ nohup bash script1.sh & nohup bash script2.sh & nohup bash script3.sh &

Daha az merakla, sadece bir sarmalayıcı komut dosyası kullanın:

$ cat script.sh
#!/usr/bin/env bash
script1.sh &
script2.sh &
script3.sh &
$ nohup script.sh &

Veya üzerlerine döngü yapın:

for script in dir/*.sh
do
    nohup bash "$script" &
done

2

Kendinizi yazmak için biraz çaba harcamak istiyorsanız

eval "nohup bash "script{1..3}.sh" &"

Ya da ikinci düşüncelerde, belki değil


1

Bu aracı satın alın: https://github.com/wagoodman/bashful

Sahip Say mytasks.yamlile

tasks:
    - name: A title for some tasks
      parallel-tasks:
        - cmd: ./script1.sh
        - cmd: ./script2.sh -x an-arg
        - cmd: ./script3.sh -y some-other-arg

Ve sen şöyle koşuyorsun:

nohup bashful run mytasks.yaml

Komut dosyalarınız dikey bir ilerleme çubuğuna paralel olarak çalıştırılır (daha önce çalıştırdıysanız ve zaman belirleyiciyse + eta). Burada verilen 3'ten daha fazlasını çalıştırmaya başlarsanız, paralel olarak kaç görev yapmak istediğinizi değiştirebilirsiniz:

config:
    max-parallel-commands: 6
tasks:
    ...

Feragatname: Ben yazarım.


0

Az önce yazdığım çok daha basit bir yardımcı program öneriyorum. Şu anda par olarak adlandırılıyor, ancak yakında parl veya pll olarak yeniden adlandırılacak, henüz karar vermediler.

https://github.com/k-bx/par

API şu kadar basit:

par "script1.sh" "script2.sh" "script3.sh"

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.