(bash) Tập lệnh A, đợi tập lệnh B, nhưng không xử lý tập lệnh con


9

Vì vậy, tôi có scriptA mà:

ssh server1 -- scriptB &
ssh server2 -- scriptB &
ssh server3 -- scriptB &
wait
otherstuffhappens

ScriptB có:

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
exit

Kết quả mong muốn của tôi là scriptA sẽ đợi tất cả các phiên bản của scriptB kết thúc trước khi tiếp tục, điều này hiện đang làm, tuy nhiên nó cũng đang chờ các rsyncs nền của những thứ không quá quan trọng. Đây là những tệp lớn hơn mà tôi không muốn chờ đợi.

Tôi đã đọc qua Sự khác biệt giữa nohup, disown và & và thử các kết hợp khác nhau, nhưng tôi không nhận được kết quả mà tôi đang tìm kiếm.

Tại thời điểm này, tôi khá bối rối. Bất kỳ trợ giúp sẽ được đánh giá cao!

Câu trả lời:


15

Vấn đề ở đây là việc sshdchờ kết thúc tập tin trên đường ống mà nó đang đọc thiết bị xuất chuẩn của lệnh (không phải thiết bị lỗi chuẩn vì một số lý do, ít nhất là với phiên bản tôi đang thử nghiệm). Và công việc nền kế thừa một fd cho đường ống đó.

Vì vậy, để giải quyết vấn đề đó, hãy chuyển hướng đầu ra của rsynclệnh nền đó sang một số tệp hoặc /dev/nullnếu bạn không quan tâm đến nó. Bạn cũng nên chuyển hướng stderr, bởi vì ngay cả khi sshd không đợi đường ống tương ứng, sau khi sshdthoát, đường ống sẽ bị hỏng nên rsyncsẽ bị giết nếu nó cố gắng viết trên stderr.

Vì thế:

rsync ... > /dev/null 2>&1 &

Đối chiếu:

$ time ssh localhost 'sleep 2 &'
ssh localhost 'sleep 2 &'  0.05s user 0.00s system 2% cpu 2.365 total
$ time ssh localhost 'sleep 2 > /dev/null &'
ssh localhost 'sleep 2 > /dev/null &'  0.04s user 0.00s system 12% cpu 0.349 total

Và:

$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null &'; sleep 2; cat out
141  # ls by killed with SIGPIPE upon writing the error message
$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null 2>&1 &'; sleep 2; cat out
2    # ls exited normally after writing the error on /dev/null instead
     # of a broken pipe


3

Các -flá cờ để sshsửa chữa vấn đề. Đã thử nghiệm trên:

#!/bin/sh -e
echo $$_script__begin
( echo sleeping; sleep 2; echo slept )&
echo $$_script__end

Khi tôi chạy nó ssh localhost ./script, nó đợi cho đến khi sleptxuất hiện. Với -fcờ, nó thoát ra echo $$_script__endsleptsau đó hiển thị trong nền sau khi sshlệnh đã trở lại.


2

Đây là một sự cố đã biết của máy chủ OpenSSH, được mô tả và thảo luận trong lỗi ngược dòng # 2071 . Trong lỗi này, có một số cách giải quyết được đề xuất ở phía OpenSSH, nhưng cũng cho kịch bản.

Nếu bạn muốn chờ đợi cho đầu ra của kịch bản, bạn nên thêm một waittrước exitcủa scriptBquá.

Nếu bạn không quan tâm đến đầu ra, hãy sử dụng một số biến thể nohupvà chuyển hướng IO tới /dev/null, điều này sẽ giải quyết vấn đề theo cách tương tự.


1

Bạn có thể thử điều này. $!là biến shell mặc định chứa ID tiến trình của đường ống / quy trình nền được thực hiện gần đây nhất.

command1 &
lpid1=$!

command2 &
lpid2=$!

command3 &
lpid=$!

wait $lpid1  # waits for only the process with PID lpid1  to complete. 

Bạn cần sử dụng điều này theo kịch bản của bạn bằng cách sử dụng exportbiến vv


1

B chỉ cần đợi các quá trình nền của chính nó:

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
wait
exit

Tại thời điểm đó, bạn có thể không chạy rsync thứ hai trong nền và tránh sử dụng waithoàn toàn. Mặc dù tôi đoán OP có nghĩa là làm gì để chạy rsyncsong song cả hai quá trình, điều đó có nghĩa là làm nền cho cả hai (với &) và sau đó sử dụng wait. Trong mọi trường hợp, tôi đồng ý rằng đây là cách đơn giản nhất để khắc phục sự cố và là cách tôi chọn dựa trên thông tin trong câu hỏi.
David Z
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.