Làm thế nào để tôi biết khi một lệnh chạy qua ssh đã kết thúc?


1

Tôi đang tạo các kịch bản triển khai cho dự án của mình và tôi đang tạo một chức năng có thể chạy lệnh cả cục bộ và từ xa (trên máy chủ thông qua ssh) và trả về đầu ra văn bản.

Khi chạy một lệnh cục bộ, tôi có thể dễ dàng biết liệu lệnh đã kết thúc hay chưa bằng cách chờ đợi PID của nó. Khi tôi gửi lệnh qua kết nối SSH đang mở, tôi sẽ nhận lại đầu ra, nhưng tôi không biết lệnh đã thoát hay nếu lệnh vẫn đang chạy và sẽ tạo thêm đầu ra sau này.

Hiện tại tôi đã "giải quyết" điều này bằng cách mở một kết nối mới đến máy chủ cho mỗi lệnh, điều không cần phải nói là rất đáng kinh ngạc chậm .

Đây có vẻ như là một vấn đề phổ biến và có thể có một giải pháp đơn giản, thậm chí có thể là một thứ gì đó được tích hợp trong SSH, vì vậy tôi hỏi ở đây: Làm thế nào tôi có thể, qua một kết nối SSH mở, biết liệu các lệnh tôi đã gửi xong. Nếu tôi bằng cách nào đó có thể thu thập mã thoát quá thì đó sẽ là tuyệt vời.


Để đưa ra một ví dụ cụ thể hơn, điều này về cơ bản thể hiện vấn đề của tôi trong Ruby:

io = IO.popen(["ssh", "-q", "my-server"], "r+")

io.write("some command\n")

# Sleep for some arbitrary amount of time, because I don't know when the
# command has finished :(
sleep 1

output = io.readpartial(1_000_000)

io.write("some command\n")

# Sleep for some arbitrary amount of time, because I don't know when the
# command has finished :(
sleep 1

output = io.readpartial(1_000_000)

Điều gì về việc thực thi một tập lệnh và xử lý như được chạy cục bộ hoặc đưa ra một lệnh dài (đại loại như) Mycommnad; InterestingPID=$? ; ... ;wait $InterestingPID như lệnh đa dòng của lệnh ssh? Bạn có thể sử dụng BTW wait?
Hastur

@Hastur Tôi sợ tôi không hiểu ý của bạn ...
Hubro

Tôi xin lỗi tôi đã không đủ rõ ràng. Tôi tưởng tượng bạn muốn làm một cái gì đó như thế này , bắt được lệnh PID của lệnh, ví dụ: ( my_command -myoptions AndParameters ) với LetsStoreInterestingPID=$? ngay sau lệnh và sau một số lệnh khác wait $LetsStoreInterestingPID...
Hastur

Câu trả lời:


2

Gói lệnh của bạn trong một tập lệnh sẽ thông báo cho bạn khi hoàn thành.

Nếu bạn có sẵn máy chủ SMTP sẽ chấp nhận các email gửi đi từ máy chủ của bạn, bạn có thể sử dụng nó.

Ví dụ dưới đây sẽ thực thi your-command, chụp đầu ra của nó và stderr vào một tệp, sau đó sử dụng malix để gửi kết quả. Chắc chắn có một cách tốt hơn để đảm bảo rằng tệp đầu ra được ghi là duy nhất so với sử dụng $$ pseudovariable (có thể sử dụng một thói quen tạo ra một chuỗi ngẫu nhiên).

#/bin/bash
your-command > /tmp/$$.$0.output 2>&1
RESULT=$?
echo >> /tmp/$$.$0.output
echo "Exit code $RESULT" >> /tmp/$$.$0.output
cat /tmp/$$.$0.output | mailx -s "your-command has finished with exit code $RESULT." you@some-mail-server.invalid
rm /tmp/$$.$0.output

Nếu bạn muốn một cái gì đó cho phép bạn chỉ định một hàng lệnh, hãy xem xét Bộ đệm nhiệm vụ ( apt-get install tsp trên Debian) cho phép bạn thêm và xóa các lệnh từ hàng đợi và tôi tin rằng thậm chí có thể gửi email cho bạn đầu ra của chúng.

Đọc câu hỏi của bạn cẩn thận hơn ... có vẻ như bạn đang điều trị những gì kết nối SSH đang nhập / xuất dưới dạng luồng I / O thô.

SSH cung cấp một đường ống được mã hóa và có một số tính năng để chuyển tiếp cổng và không nhiều tính năng khác. Thứ điển hình được kết nối với đường ống đó là một cái vỏ thường mong đợi một người dùng tương tác ở đầu bên kia.

tôi suy nghĩ chìa khóa đơn có thể phần nào đạt được những gì bạn đang cố gắng thực hiện một cách dễ dàng, nhưng điều dễ nhất sẽ là tạo một tập lệnh bao bọc nhỏ thực hiện điều này:

#/bin/bash
$@ 
echo "==== Command Output Finished ===="

và sau đó tìm chuỗi ==== Command Output Finished ==== trong thói quen I / O của bạn để xác định vị trí ranh giới giữa các đầu ra lệnh. Tất nhiên bạn phải chọn một cái gì đó không thể là một phần của đầu ra hợp lệ cho một lệnh. Một kế hoạch phức tạp hơn là có thể.

SMTP làm một cái gì đó tương tự với các tiêu đề ranh giới của nó.


Vấn đề của tôi là tôi đang thực hiện các lệnh nhanh như find -type f -exec chmod 664 Mất 0,001 giây hoặc lâu hơn. Khi tôi mở kết nối SSH cho mỗi lệnh như vậy, cuối cùng chúng sẽ mất nhiều giây, điều này làm cho tập lệnh triển khai của tôi bị chậm. Liên quan đến máy chủ SMTP và thư có thể sẽ không khắc phục được ...
Hubro

@Hubro Tạo danh sách lệnh để thực thi và sử dụng giải pháp này có thể giúp đỡ? (người có cat list_of_command | ssh ... )
Hastur

Tôi đã cập nhật câu trả lời của mình.
LawrenceC

Điều này trông giống như những gì tôi đã lên kế hoạch như là giải pháp sao lưu của tôi. Tôi nghĩ rằng tôi sẽ tạo ra một chuỗi SHA1 ngẫu nhiên và nối thêm ; echo "$? c8m2js7a9... sau mỗi lệnh tôi gửi đến máy chủ và sử dụng lệnh đó để biết khi nào lệnh kết thúc và đọc trạng thái thoát. Tôi chỉ hy vọng có lẽ có một giải pháp tao nhã hơn, như chạy các lệnh như bình thường mà thực sự được thực thi trên máy chủ từ xa.
Hubro

0

Nếu bạn giữ giải pháp cho mỗi lệnh chạy trong một phiên SSH riêng, bạn có thể tăng tốc thời gian cần thiết để bắt đầu mỗi phiên bằng cách sử dụng kết nối đã mở. Điều này có nghĩa là bạn chỉ phải trả phí kết nối một lần, làm cho các phiên tiếp theo nhanh chóng bắt đầu.

Cách đơn giản nhất để thiết lập nó là mở kết nối đầu tiên với điều này:

ssh -M -S /tmp/ssh_mux_%h_%p_%r myserver

Sau đó mở từng kết nối tiếp theo với:

ssh -S /tmp/ssh_mux_%h_%p_%r myserver "command"

Có nhiều thông tin hơn trong ssh_config trang dưới ControlMasterControlPathhoặc trực tuyến đây đây .

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.