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?

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.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.