Tại sao chức năng không trở lại cho đến khi quá trình nền kết thúc?


21

Hãy xem xét kịch bản này:

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

Kịch bản không tiếp tục qua quá trình đóng của nó cho đến khi quá trình leafpad kết thúc, mặc dù đó là một quá trình nền.

Tại sao lại thế này? Có thể khởi chạy một quá trình nền từ một chức năng?

Câu trả lời:


22

Hàm trả về, nhưng khối thay thế lệnh, bởi vì bạn đã tạo một công việc nền, nhưng bạn vẫn mở fdout stdout của mình. Chỉ cần đóng nó bằng cách thêm >/dev/nulltrước &.

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

Nếu bạn muốn tiến trình của mình cũng có stdin, stdout, stderr đã đóng, hãy sử dụng điều này:

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

Điều này sẽ đóng stdin (0), stdout (1) và stderr (2), sau đó là nền (&). Ngoài ra, khi sử dụng các chuyển hướng luồng này, đừng quên chúng bị "lừa", điều đó có nghĩa là trùng lặp theo thứ tự thực hiện.

1>/dev/null 2>&1

2>&1 1>/dev/null

không giống nhau ! Trước đây, bạn đang sao chép một luồng thành / dev / null (đó là những gì bạn muốn), sau đó, bạn đang sao chép / dev / stdout thành stderr, và sau đó, đóng stdout. Vì vậy, bất kỳ tin nhắn được gửi đến stderrsẽ xuất hiện trong bảng điều khiển của bạn.


Xác nhận trên hệ thống của tôi
user120161

10
Bạn không đóng luồng, bạn đang chuyển hướng chúng.
dcat

4
đóng; n>&-nơi nlà mô tả tập tin.
dcat

1
@dcat: Có, nhưng việc chuyển hướng đến / từ /dev/nullsẽ không dẫn đến lỗi i / o khi một quá trình cố gắng viết thiết bị xuất chuẩn của nó, nhưng thấy rằng đó 1là một FD không hợp lệ. Vì vậy, thuật ngữ trong bài viết là sai, không phải là lập trình bash thực tế. (Trên thực tế, sao chép FD 1-0 phương tiện mà stdin sẽ là một tập tin mô tả mở với O_RDONLY, mà có lẽ sẽ đưa ra một lỗi (chứ không phải là mong muốn không-byte-có sẵn) khi cố gắng quá trình đọc.) Ví dụ wc >/dev/null 0>&1->wc: standard input: Bad file descriptor
Peter Dây

1
@PeterCordes - Đóng mô tả cũ và chuyển hướng cái mới không cần phải loại trừ lẫn nhau. exec <&- >&- <>/dev/null >&0xử lý stdin / ra khá triệt để. Nó tạo ra sự khác biệt zshít nhất là sẽ sắp xếp tất cả các phần mở trên cùng một bộ mô tả khi nhiều bộ được đặt.
mikeerv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.