Mengapa tidak berfungsi kembali sampai proses latar belakang berakhir?

21

Pertimbangkan skrip ini:

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

Script tidak melanjutkan melewati penjepit penutupan sampai proses leafpad berakhir, meskipun itu adalah proses latar belakang.

Kenapa ini? Apakah mungkin untuk meluncurkan proses latar belakang dari suatu fungsi?

pengguna234565
sumber

Jawaban:

22

Fungsi kembali, tetapi substitusi perintah blok, karena Anda membuat pekerjaan latar belakang, tetapi Anda masih memiliki stdout Anda dibuka. Tutup saja dengan menambahkan >/dev/nullsebelum &.

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

Jika Anda ingin proses Anda juga memiliki stdin, stdout, stderr ditutup, gunakan ini:

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

Ini akan menutup stdin (0), stdout (1), dan stderr (2), lalu latar belakang (&). Juga, ketika menggunakan pengalihan aliran ini jangan lupa mereka "ditipu", itu berarti digandakan dalam urutan eksekusi.

1>/dev/null 2>&1

dan

2>&1 1>/dev/null

tidak sama ! Di yang pertama, Anda menduplikasi aliran ke / dev / null (yang Anda inginkan), di yang terakhir, Anda menduplikasi / dev / stdout ke stderr, dan kemudian, menutup stdout. Jadi setiap pesan yang dikirim ke stderrakan muncul di konsol Anda.

Adrien M.
sumber
Dikonfirmasi pada sistem saya
user120161
10
Anda tidak menutup aliran, Anda mengarahkan mereka.
dcat
4
untuk menutup; n>&-dimana ndeskriptor file.
dcat
1
@dcat: Ya, tetapi pengalihan ke / dari /dev/nulltidak akan menyebabkan kesalahan i / o ketika suatu proses mencoba untuk menulis stdout-nya, tetapi menemukan bahwa itu 1adalah FD yang tidak valid. Jadi terminologi dalam posting salah, bukan pemrograman bash yang sebenarnya. (Sebenarnya, menduplikasi FD 1 ke 0 berarti stdin akan menjadi file-descriptor yang dibuka O_RDONLY, yang mungkin akan memberikan kesalahan (daripada no-bytes yang diinginkan tersedia) ketika proses mencoba membaca.) Mis wc >/dev/null 0>&1->wc: standard input: Bad file descriptor
Peter Cordes
1
@PeterCordes - Menutup deskriptor lama dan mengarahkan yang baru tidak harus saling eksklusif. exec <&- >&- <>/dev/null >&0menangani stdin / out cukup lengkap. Itu membuat perbedaan zshsetidaknya yang akan mengurutkan semua terbuka pada deskriptor yang sama secara otomatis ketika multios diatur.
mikeserv