Yarı asenkron boru


11

Aşağıdaki boruya sahip olduğumu varsayın:

a | b | c | d

Nasıl tamamlanması için bekleyebilir c(veya b) 'de shya bash? Senaryo olduğunu bu araçlar dher zaman başlayabilir (ve yok değil bekledi gerekir) ama komple çıkışı gerektirir cdüzgün çalışması için.

Kullanım durumu olduğu difftooliçin gitbu görüntüleri karşılaştırır. Tarafından çağrılır gitve girdisini ( a | b | cparça) işlemek ve karşılaştırmanın sonuçlarını ( dparça) görüntülemek gerekir. Arayan ave için gereken girdiyi siler b. Bu, komut dosyasından dönmeden önce işlemin c(veya b) sonlandırılması gerektiği anlamına gelir . Öte yandan, bekleyemiyorum dçünkü bu, kullanıcı girdisini beklediğim anlamına geliyor.

Sonuçlarını cgeçici bir dosyaya yazabileceğimi veya belki bir FIFO kullanabileceğimi biliyorum bash. (Ancak FIFO'nun yardımcı olup olmayacağından emin değilim.) Bunu geçici dosyalar olmadan başarmak mümkün mü sh?

DÜZENLE

Belki de c(veya b) sürecin süreç kimliğini güvenilir bir şekilde bulabilmem yeterli olacaktır . Sonra tüm boru asenkron olarak başlatılabilir ve bir işlem kimliği bekleyebilirim. Çizgisinde bir şey

wait $(a | b | { c & [print PID of c] ; } | d)

DÜZENLEME ^ 2

Bir çözüm buldum, yorumlar (veya daha iyi çözümler) bekliyoruz.


Yani çıktısını ancak tamamlandıktan sonra dmı başlatmak istiyorsunuz ? Her çıkış hattını geldiği gibi işlemeye başlamak istemiyor musunuz? ccd
terdon

@terdon: Hayır, distediği zaman başlamak ücretsizdir, ancak devam cetmeden önce bitirmem gerekiyor.
krlmlr

Bu kendinden çelişkili gibi görünüyor, eğer istediği dzaman başlayabilirse, tam olarak ne bekliyorsunuz?
terdon

@terdon: Kullanım durumunu göstermek için genişletildi.
krlmlr

Çıktısını dkullanmazsa , boru hattının bir parçasını cyapmak mantıklı görünmüyor d. Ancak dgirdiyi kullanıyorsa, dyaklaşımınızın herhangi bir fark yaratması için hepsini okuduktan sonra girdisinde bir süre çalışmalıdır.
Hauke ​​Laging

Yanıtlar:


6
a | b | { c; [notify];} | d

Bildirim, örneğin bir ortam değişkeninde ( kill -USR1 $EXTPID) geçirilmiş bir PID'ye sinyal gönderilerek veya bir dosya ( touch /path/to/file) oluşturularak yapılabilir.

Diğer bir fikir:

Bir sonraki işlemi (beklemek için başlayabileceğiniz işlemi) boru hattından yürütürsünüz:

a | b | { c; exec >&-; nextprocess;} | d

veya

a | b | { c; exec >&-; nextprocess &} | d

Teşekkürler. Ancak daha sonra, ara çıktı için geçici bir dosya oluşturmak daha ayrıntılı ve ayrıştırılması daha kolaydır (bir insan için). Ayrıca, sinyal ile yarış durumundan nasıl kaçınırım? ... daha temiz bir çözüm umuyordum, ama eğer gidilecek yol buysa, öyle olsun.
krlmlr

@krlmlr Hangi yarış durumu?
Hauke ​​Laging

notifysinyal tuzağını kurmadan önce çalıştırılabilir. Bu sinyali kaçırmamaya nasıl emin olabilirim?
krlmlr

@krlmlr Boru hattını çağıran komut dosyasını trap, tanımlandıktan sonra gönderilen bir sinyal alana kadar durdurursunuz .
Hauke ​​Laging

Düzenlemeniz: Boru, üzerinde hiçbir kontrolüm olmayan bir döngüde çağrılır. Ne yazık ki, { c; bg; }ya da { c; exit 0; }çalışmıyor gibi görünüyor.
krlmlr

5

Sorunuzu doğru anlarsam, bu işe yarayacaktır:

a | b | c | { (exec <&3 3<&-; d) &} 3<&0

(fd 3 hilesi, bazı (çoğu) mermilerin stdin'i / dev / null'a yönlendirmesidir &).



3

Hauke'nin girdisinin yardımıyla deneme yanılma yoluyla bulduğum şey bu:

a | b | { c; kill -PIPE $$; } | d

eşdeğer bir:

a | b | ( c; kill -PIPE $$; ) | d

(İkincisi daha açıktır, çünkü {}bir borunun içindeyse bir alt kabukta çalışacaktır.)

(Dahil olmak üzere bazı diğer sinyaller QUIT, TERMve USR1çalışma,), çok, ancak bu durumda, sinyal tanımı terminali gösterilir.

Bunun PIPEsinyalin orijinal niyeti olup olmadığını merak ediyorum . El kitabına göre :

SIGPIPE: PIPESinyal, diğer uca bağlı bir işlem olmadan bir boruya yazmaya çalıştığında bir işleme gönderilir.

Bu, alt kabuğa yapay olarak bir boru sinyali gönderdiğimde, son tüketiciyi ( d) yalnız bırakarak sessizce sonlandırıldığı anlamına gelir .

Bu, hem çalışır shve bash.


0

Sen kullanabilirsiniz sponge"moreutils" paket programı:

a | b | c | sponge | d

sünger cborulamadan önce çıkışının sonu için olacaktır d. Umarım istediğin buydu.


0

Sadece şunları yapabilirsiniz:

a | b | c | (d ; cat > /dev/null)

Böylece, dbittiğinde, catgeri kalanını cbitene kadar emer .

Tamam. Yorumlardan sonra, cevabın doğrudan darka planda başlamak olduğunu düşünüyorum .

Yapmak:

a | b | c | (d &)

veya stdin'den okuma ile ilgili sorunlar varsa Stephane Chazelas'ın çözümünü kullanın .d


Korkarım kullanım durumum oldukça farklı: cdaha önce bitiyor dve bitene kadar beklemek zorundayım cama umrumda değil d.
krlmlr

Üzgünüm, anlamadım. cİşiniz bittiğinde ve dhala çalışıyorken ne yapmak istiyorsunuz ? Öldürmek dmi?
angus

dbir GUI'ye sahiptir ve kullanıcı onu kapatana kadar çalışabilir.
krlmlr

Tamam ... ama bu zaten oluyor. Ne zaman a, bve cişlerini bitirdiklerinde, stdout'u kapatırlar ve çıkarlar; ve sadece dkoşuyor. Tamamlandığında darka plana göndermek ister misiniz c? Öyle mi?
angus

Evet, bittiğinde darka plana gönderilmelidir c.
krlmlr
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.