Bash, bazı arka plan süreçlerinin çalışmasına nasıl izin verilir, ancak diğerleri için beklenir?


11

Ben (henüz) bir tane daha wait, &, &&denetim akışı soru ..

Mümkün olduğu kadar aynı anda çalışmak istiyorum böyle bir komut dosyası var demek:

# may take some hours
something InputA > IrrelevantA &
something InputB > IrrelevantB &

# may take an hour
(
   somethingElse InputA > OutputA &
   somethingElse InputB > OutputB &
)&& combine OutputA OutputB > Result

...morestuff

Soru 1: Komut dosyasında, combineher somethingElseiki somethingişlem devam ederken her iki işlemin de bitmesini bekliyor mu?

Soru 2: Değilse - ve şüphelenmiyorum - yukarıdaki işlemler arka planda çalışmaya devam ederken combinesadece her iki somethingElseişlemi de nasıl bekleyebilirim something?

Yanıtlar:


13

Örneğinizde, combinekomut alt kabuk çıkar çıkmaz çalıştırılır (ve son arka plan işleminin hatasız başlatılması koşuluyla). waitKomut olmadığı için alt kabuk işler başladıktan hemen sonra çıkacaktır .

İki veya daha fazla eşzamanlı arka plan işleminin dönüş değerine dayalı bir komut yürütmek istiyorsanız, dönüş değerleri için geçici dosyaları kullanmak dışında başka bir yol göremiyorum. Bunun nedeni wait, yalnızca beklediği işlemlerden birinin dönüş değerini döndürebilmesidir . Ayrıca, dönüş değerlerini almak için arka plan işlemlerinin alt kabuklarda çalıştırılması gerektiğinden, değişkenlerde depolanamazlar. Şunları yapabilirsiniz:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

tmp1=$(mktemp)
tmp2=$(mktemp)

( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!

( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!

wait "$proc1" "$proc2"

read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result

rm "$tmp1" "$tmp2"

Dönüş değerlerini gerçekten önemsemiyorsanız, işleri normal şekilde başlatabilir ve kullanabilirsiniz wait:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

somethingElse InputA >OutputA &
proc1=$!

somethingElse InputB >OutputB &
proc2=$!

wait "$proc1" "$proc2"
combine OutputA OutputB >Result

Merhaba, 2. seçeneğin benim için çalışacağını düşünüyorum ...
Stephen Henderson

3

Misiniz süreç ikamesi dosyaları kaydetmek gerekmez, özellikle daha verimli OutputAve OutputBve sadece umurumda Result? Diske yazmada yavaş bir G / Ç'niz varsa, dosyaları kaydederken OutputAve OutputBhız sınırlayıcı adım olabileceğinden bu özellikle zaman kazandırır mı?

combine  <(somethingElse InputA)  <(somethingElse InputB)  >  Result

İşlem ikamesi <(..here..), çıktıyı bir dosyaya kaydetmek yerine "kombine" adımında girdi olarak okumak yerine komutu koymanızı sağlar .

Bellek bir sınırlama ise ve belleğin tutabileceğinin boyutu outputAve outputBfazlası, tüm amacı yener mi?

Her combineiki işlem de çalışmaya başlamadan önce tamamlanacak mı?


Bu “Tehlike” değildir; lütfen not deyim bir soru şeklinde yanıtınızı. Cidden, yeni bir fikir buldun ve bence oldukça iyi. Birkaç noktanıza yanıt vermek için: combineiki somethingElsekomut başlar başlamaz çalışmaya başlayacaktır , ama sorun değil, çünkü <(…)işler birer boru; bu nedenle combine, somethingElsesüreçleri geçerse verileri beklemek zorunda kalacaktır . Ve onlar boru oldukları için boyut bir sorun değil. … (Devam ediyor)
G-Man, 5

(Devam)… Cevabınızla ilgili tek temel sorun, somethingElsesüreçlerin çıkış durumunun test edilmesine izin vermemesidir - ve bunun asker için önemli olup olmadığı tamamen açık değildir. Ama aynı zamanda bir cevap böyle sorular sormamalı.
G-Man 'Monica'yı Yeniden Başlat' diyor

2

waitKomutu kullanabilirsiniz :

(echo starting & sleep 10 & wait) && echo done

"Başlangıç" çizgisinin hemen gerçekleştiğini görebilirsiniz ve "tamamlandı" 10 saniye bekler.


genellikle bekleme, aynı kabuğun alt süreçlerini gerektirir. Bekle biraz zor.
mikeserv

1
@mikeserv, neden bahsediyorsun? Mesele bu: Bu alt kabuktaki tüm çocukları bekliyor.
psusi

ilk testlerimde bu işe yarıyor. Şimdi büyük senaryoda deneyeceğim
Stephen Henderson

Tam olarak - aynı kabuktaki çocuklar - alt kabuklar. Kaçmaya çalışmayan ya da arka plana ya da başka bir şey yapmayan herhangi bir işlem için çalışmalıdır. Demek istediğim tek şey - süreçleriniz süreç liderlerine saygı gösterdiği sürece beklemek iyidir, ancak bir süreç kendi süreç lideri olmaya çalıştığında, bekleme sorunları olacaktır.
mikeserv

0

Aslında bu tür şeylerin başka bir yanıt yapılabilir olabilir tam olarak nasıl göstermek burada . Bu yanıt, 2 günlükün bir arka plan işlemi tarafından korunmasını sağlamakla ilgili bir soruydu, bu yüzden 10 ile gösterdim.

Demo Komut Dosyası

cat <<-\DEMO >|${s=/tmp/script} 
printf 'tty is %s\nparent pid is %s\npid is pid=%s\n' \
     "$(tty)" "$PPID" "$$"
exec 1>&2 ; nums=$(seq 0 9)
rm ${files=$(printf "/tmp/file%s\n" $nums)}
for n in $nums ; do { for f in $files ; do
    echo "Line $n" >>"$f" ; done
sleep 1 ; } ; done
#END
DEMO

Demoyu Çalıştır

s=/tmp/script ;chmod +x $s ;info="$(($s &)2>&- &)"
echo "$info" ; pid="${info##*=}" ; echo
while ps -p $pid >/dev/null ; do sleep 3 ; done
for f in /tmp/file[0-9] ; do
    printf 'path : %s\tline count : %s\n' \
        $f $(<$f wc -l)
done

Çıktı:

tty is not a tty
parent pid is 1
pid is 12123

path : /tmp/file0    line count : 10
path : /tmp/file1    line count : 10
path : /tmp/file2    line count : 10
path : /tmp/file3    line count : 10
path : /tmp/file4    line count : 10
path : /tmp/file5    line count : 10
path : /tmp/file6    line count : 10
path : /tmp/file7    line count : 10
path : /tmp/file8    line count : 10
path : /tmp/file9    line count : 10

Yukarıda gösterilmiştir. Adında bir komut dosyası oluşturur ve çalıştırır /tmp/script, chmod' yürütülebilir olarak ' ve &backgroundbir &backgrounded ( subshell ).

Senaryo rms /tmp/file0-910 dosya ve 10 echoessaniyede bir satır. Ben $infoinkâr edilmemiş süreç bazı yakalama $(command substitution). While psve $pidben yakalama hakkında hala raporlar aracılığıyla sunmak , ben hala çalışır biliyorum böylece I sleep.Tamamlandığında, 10 dosyadaki satırları ile sayılırwc.

Bir süreci bu şekilde çağırdıktan sonra, orijinal ana sürecini özgürce kapatabilirsiniz ve bu da kamyon taşımacılığına devam eder - etkili bir şekilde reddedilir. Bu aynı zamanda geleneksel kullanamazsınız demektir waitkomutu, ancak bekleyen psbireyin karşılığında her durumda daha sağlam olmalıdır.

Bahsetmeye değer, bence, süreç aslında başlangıçta çağrılıyor $(command substitution)ve printfsben de $infoistiyorum, böylece onu etkili bir şekilde kontrol edebiliyorum. Ama onun uç çıkışını düşer kısa sürede exec 1>&2(ki ile aynı alt kabukta kapalıdır 2>&-), süreç kaçar ve ben diğer ucunda bunun için beklemek zorunda. Her iki dünyanın da en iyisi, özellikle de giriş borularını işlemek için kullanırsanız, zihninizi tüm yönlendirmeler ve süreç liderlerinin etrafına sarabilirsiniz.

Diğer her şey sadece burada gösteri içindir. Bunu çalıştırmak için tek ihtiyacınız olan en iyi komut dosyası ve:

info="$(($script_path &)2>&- &)"    

NOT: Bu yalnızca tam olarak göstermek istediğimi terminale yazdırır. Belirtildiği gibi,$PPID,bu işlem terminal tarafından reddedilir ve doğrudan bir çocuktur.$PID 1.

Bunlardan ikisini aynı anda çalıştırmak ve onları beklemek isterseniz, psher iki pidesini de teslim edebilir ve bekleyebilirsiniz.

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.