Arkaplan işlemi sona erene kadar neden fonksiyon geri dönmüyor?


21

Bu betiği düşünün:

#!/bin/bash
function start {
  leafpad &
  echo $!
}
PID=$(start)
echo "PID is $PID"

Senaryo, arka plan işlemi olsa bile, yaprak tabanı işlemi sona erene kadar kapanış ayracını geçmiyor.

Bu neden? Bir işlevden bir arka plan işlemi başlatmak mümkün mü?

Yanıtlar:


22

İşlev geri döner, ancak komut değiştirme işlemi, arka plan işi oluşturduğunuz için engellenir, ancak yine de stdout fd'nizi açarsınız. Sadece >/dev/nullönce ekleyerek kapatın &.

#!/bin/bash
function start {
  leafpad >/dev/null &
  echo $!
}
PID=$(start)
echo "PID is $PID"

İşleminizin ayrıca stdin, stdout, stderr kapalı olmasını istiyorsanız, şunu kullanın:

leafpad >/dev/null 0>&1 2>&1 &

Bu stdin (0), stdout (1) ve stderr (2) 'yi, ardından arkaplanı (&) kapatır. Ayrıca, bu akış yönlendirmeleri kullanılırken, bunların "duped" olduklarını unutma, bu, yürütme sırasına göre çoğaltılmış demektir.

1>/dev/null 2>&1

ve

2>&1 1>/dev/null

aynı değiller ! Birincisinde, / dev / null dizinine bir akışı çoğaltırsınız (ki istediğiniz budur), ikincisinde, / dev / stdout komutunu stderr öğesine kopyalar ve sonra stdout'u kapatırsınız. Böylece gönderilen herhangi bir mesaj stderrkonsolunuzda görünecektir.


Sistemimde onaylandı
user120161

10
Akışları kapatmıyorsunuz, yönlendiriyorsunuz.
dcat,

4
kapatmak; dosya tanımlayıcısı n>&-nerede n.
dcat,

1
@dcat: Evet, ancak / dan yeniden yönlendirme /dev/null, bir işlem stdout'unu yazmaya çalıştığında g / Ç hatalarına neden olmaz, ancak bunun 1geçersiz bir FD olduğunu bulur . Bu yüzden postdaki terminoloji yanlış, asıl bash programlama değil. (Aslında, FD 1 ila 0'ın çoğaltılması, stdin'in açılmış bir dosya tanıtıcısı O_RDONLYolacağı ve işlemin okumaya çalıştığı zaman büyük olasılıkla bir hata (arzu edilen baytların bulunmadığı yerine) olacağı anlamına gelir.) Eg wc >/dev/null 0>&1->wc: standard input: Bad file descriptor
Peter Kordonlar

1
@PeterCordes - Eski tanımlayıcıyı kapatmak ve yenisini yönlendirmek için birbirini dışlamak gerekmez. exec <&- >&- <>/dev/null >&0oldukça yorucu biçimde stdin / out yapar. zshEn azından multios ayarlandığında otomatik olarak aynı tanımlayıcıdaki tüm açılışları bir araya getirecek şekilde fark yaratır.
mikeserv
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.