Làm thế nào để có được danh sách tất cả các tiến trình con được sinh ra bởi một tập lệnh


8

Bối cảnh:

Người dùng cung cấp cho tôi các tập lệnh tùy chỉnh của họ để chạy. Các tập lệnh này có thể thuộc bất kỳ loại nào như tập lệnh để bắt đầu nhiều chương trình GUI, dịch vụ phụ trợ. Tôi không có quyền kiểm soát về cách các kịch bản được viết. Các tập lệnh này có thể thuộc kiểu chặn tức là thực thi chờ cho đến khi tất cả các tiến trình con (chương trình được chạy tuần tự) thoát ra

#exaple of blocking script
echo "START"
first_program 
second_program 
echo "DONE"

hoặc loại không chặn, tức là loại mà fork con xử lý trong nền và thoát khỏi cái gì đó như

#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"

Tôi đang cố gắng đạt được điều gì?

Các tập lệnh do người dùng cung cấp có thể thuộc bất kỳ loại nào trong hai loại trên hoặc kết hợp cả hai. Công việc của tôi là chạy tập lệnh và đợi cho đến khi tất cả các tiến trình bắt đầu bằng nó thoát ra và sau đó tắt nút. Nếu thuộc loại chặn, trường hợp đơn giản, tức là lấy PID của quá trình thực thi tập lệnh và đợi cho đến khi ps -ef | grep -ef PID không có thêm mục nào. Các kịch bản không chặn là những thứ gây rắc rối cho tôi

Có cách nào để tôi có thể nhận được danh sách các PID của tất cả tiến trình con được sinh ra bằng cách thực thi tập lệnh không? Bất kỳ gợi ý hoặc gợi ý sẽ được đánh giá cao


Tôi không nghĩ là có thể sau khi tập lệnh gốc kết thúc trừ khi bạn có thể nắm bắt được PID của cha mẹ. Nếu bạn đang khởi chạy các tập lệnh, bạn có thể gói chúng trong một cái gì đó giống như pid$(foo.sh; echo $!)nó sẽ cung cấp cho bạn bộ PID foo.shđể bạn có thể sử dụng ps --ppid. Công việc vừa ý?
terdon

2
Các kịch bản có phải chạy theo UID của người dùng tác giả không? Nếu không, bạn có thể tạo một người dùng giả chỉ cho mục đích này? Bạn thậm chí sẽ không cần grep, chỉ ps –udummy_user. Ngoài ra, nhìn vào các nhóm quá trình.
Scott

Đây là một loại cách giải quyết hơn là một giải pháp cho câu hỏi ban đầu của bạn: Mở một phiên bash mới. Bạn có thể liệt kê tất cả các quy trình được sinh ra từ trình bao này bằng cách sử dụng psmà không có bất kỳ đối số nào (chỉ nên bashpsbắt đầu). Bắt đầu kịch bản của bạn ở đó. Sau khi hoàn thành, chờ cho đến khi ps | wc -lđạt được giá trị mong đợi của bạn.
Tim

Câu trả lời:


6

Để trả lời câu hỏi của bạn trực tiếp, lệnh

jobs -p

cung cấp cho bạn danh sách tất cả các quá trình con.

Phương án số 1

Nhưng trong trường hợp của bạn, có thể dễ dàng hơn khi chỉ sử dụng lệnh waitmà không cần bất kỳ thông số nào:

first_program &
second_program &
wait

Điều này sẽ đợi cho đến khi TẤT CẢ các quá trình con đã kết thúc.

Phương án số 2

Một cách khác là sử dụng $!để có được PID của chương trình cuối cùng và có thể tích lũy trong một biến, như vậy:

pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"

và sau đó sử dụng chờ với điều đó (đây là trong trường hợp bạn chỉ muốn đợi một tập hợp con của các tiến trình con của bạn):

wait $pids

Phương án số 3

HOẶC, nếu bạn chỉ muốn đợi cho đến khi BẤT K process quá trình nào kết thúc, bạn có thể sử dụng

wait -n $pids

Thông tin thưởng

Nếu bạn muốn một sigterm vào tập lệnh bash của bạn để đóng các tiến trình con của bạn, bạn sẽ cần truyền tín hiệu bằng một cái gì đó như thế này (đặt cái này ở đâu đó trên cùng, trước khi bắt đầu bất kỳ quy trình nào):

trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT

1

Cảm ơn mọi người vì câu trả lời của bạn .. Tôi đã có giải pháp về stackoverflow

Bạn có thể sử dụng chờ đợi để chờ tất cả các quá trình nền được bắt đầu bởi usercript hoàn thành. Vì chờ đợi chỉ hoạt động đối với trẻ em của trình bao hiện tại, bạn sẽ cần tìm nguồn tập lệnh của chúng thay vì chạy nó như một quy trình riêng biệt.

(nguồn người dùng; chờ)

Tìm kiếm tập lệnh trong một khung con rõ ràng sẽ mô phỏng bắt đầu một quy trình mới đủ chặt chẽ. Nếu không, bạn cũng có thể đặt nền tảng con, điều này buộc một quá trình mới được bắt đầu, sau đó chờ cho nó hoàn thành.

(nguồn người dùng; chờ) & chờ

Đây là liên kết cho câu trả lời ban đầu của @chepner: https://stackoverflow.com/questions/18663196/how-to-get-list-of-all-child- process-spnedned-by-a-script / 18663969? Noredirect = 1 # 18663969


3
Tôi cũng nghĩ về điều này, nhưng giải pháp này thất bại khi usercript bắt đầu một mục con trong nền và sau đó bắt đầu một tập lệnh khác trong nền. waitLệnh của bạn sau đó sẽ đợi con của usercript chứ không phải cho cháu của nó.
Tim

@Tim Chỉ cần nhận ra rằng :(
irraju
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.