Lệnh ssh bất ngờ tiếp tục trên hệ thống khác sau khi ssh chấm dứt


11

Tôi đang chạy lệnh dưới đây và giám sát tệp đầu ra trên hệ thống khác:

ssh $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'

Nếu tôi giết lệnh ssh bằng cách sử dụng ^Choặc chỉ bằng cách giết thiết bị đầu cuối mà tôi đã đăng nhập, tôi cũng mong lệnh từ xa cũng chấm dứt. Mặc dù vậy, điều này không xảy ra: /tmp/countnhận được tất cả các số 1 trừ5 và ps -ejHhiển thị lớp vỏ và sleepcon của nó tiếp tục chạy.

Đây có phải là hành vi dự kiến, và nó được ghi nhận ở bất cứ đâu? Tôi có thể vô hiệu hóa nó? Từ việc đọc xung quanh, tôi dự kiến ​​sẽ phải kích hoạt một cách rõ ràng loại hành vi này với nohup, không phải là mặc định.

Tôi đã xem qua các trang hướng dẫn về ssh và sshd, nhưng không phát hiện ra điều gì rõ ràng và Google chỉ cho tôi các hướng dẫn để bật hành vi này chứ không phải để tắt.

Tôi đang chạy Red Hat Enterprise Linux 6.2, với đăng nhập gốc và bash shell trên cả hai hệ thống.

Câu trả lời:


11

câu trả lời của uther bảo bạn phân bổ một thiết bị đầu cuối nhưng không giải thích tại sao. Lý do không cụ thể đối với ssh, đó là vấn đề tạo và truyền tín hiệu. Tôi mời bạn đọc Điều gì gây ra các tín hiệu khác nhau được gửi? để có thêm nền tảng.

Trên máy chủ từ xa, có hai quy trình liên quan:

  • một thể hiện của ssh daemon ( sshd), đang chuyển tiếp đầu vào và đầu ra của chương trình từ xa đến thiết bị đầu cuối cục bộ;
  • Một cái vỏ, đang chạy forvòng lặp đó .

Vỏ có thể chết một cách tự nhiên khi đến cuối vòng lặp hoặc gặp lỗi nghiêm trọng hoặc xảy ra tín hiệu. Câu hỏi là, tại sao vỏ sẽ nhận được tín hiệu?

Nếu lớp vỏ từ xa được kết nối với các sshdđường ống, đó là điều xảy ra khi bạn chỉ định một lệnh trên sshdòng lệnh, thì nó sẽ chết vì SIGPIPE nếu sshdthoát ra và vỏ cố gắng ghi vào đường ống. Chừng nào cái vỏ không ghi vào đường ống, nó sẽ không nhận được SIGPIPE. Ở đây, shell không bao giờ ghi bất cứ điều gì vào đầu ra tiêu chuẩn của nó, vì vậy nó có thể sống mãi mãi.

Bạn có thể chuyển -ttùy chọn cho ssh, để bảo nó mô phỏng một thiết bị đầu cuối ở phía xa và chạy lệnh được chỉ định trong thiết bị đầu cuối này. Sau đó, nếu máy khách SSH biến mất, sshdđóng kết nối và thoát, phá hủy thiết bị đầu cuối. Khi thiết bị đầu cuối biến mất, bất kỳ quá trình nào đang chạy trong thiết bị đều nhận được SIGHUP . Vì vậy, nếu bạn giết máy khách SSH (bằng killhoặc đóng thiết bị đầu cuối mà máy khách đang chạy), vỏ từ xa bị SIGHUPped.

Nếu bạn vượt qua -ttùy chọn, SSH cũng chuyển tiếp SIGINT . Nếu bạn nhấn Ctrl+ C, thì vỏ từ xa sẽ nhận được SIGINT.


Sử dụng -ttthay vì -tnếu bản thân ssh không có phân bổ tty. SSH sẽ không nhận được tty được phân bổ nếu ssh được nền ngay lập tức khi gọi qua các tùy chọn như -fhoặc -n.
Miron V

3

Hãy thử phân bổ một psuedo-tty với sshlệnh của bạn .

ssh -t $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'

Khi bạn ngắt kết nối phiên ssh, quá trình sẽ chấm dứt.

Vì đây là giả, nên việc khởi tạo shell của bạn có thể sẽ không đến các tệp cấu hình nguồn, để lại lệnh của bạn với môi trường rất trống. Bạn có thể cần phải thiết lập một .ssh/environmenttệp xác định các biến môi trường như PATH. Từman 1 ssh

Additionally, ssh reads ~/.ssh/environment, and adds lines of the format 
“VARNAME=value” to the environment if the file exists and users are allowed
to change their environment.  For more information, see the 
PermitUserEnvironment option in sshd_config(5).

2

Thay thế cho việc sử dụng -ttùy chọn để sshlàm cho lệnh từ xa chấm dứt khi sshmáy khách thoát hoặc (bị giết), một ống có tên có thể được sử dụng để chuyển đổi "EOF thành SIGHUP" khi đóng stdin of sshd(xem Bug 396 - sshd mồ côi xử lý khi không có pty phân bổ ).

# sample code in Bash
# press ctrl-d for EOF
ssh localhost '
TUBE=/tmp/myfifo.fifo
rm -f "$TUBE"
mkfifo "$TUBE"
#exec 3<>"$TUBE"

<"$TUBE" sleep 100 &  appPID=$!

# cf. "OpenSSH and non-blocking mode", 
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2005-July/023090.html
#cat >"$TUBE"
#socat -u STDIN "PIPE:$TUBE"
dd of="$TUBE" bs=1 2>/dev/null
#while IFS="" read -r -n 1 char; do printf '%s' "$char"; done > "$TUBE"

#kill -HUP -$appPID 
kill $appPID

rm -f "$TUBE"
'

1

Đây là cách tốt nhất tôi đã tìm thấy để làm điều này. Bạn muốn một cái gì đó ở phía máy chủ cố đọc stdin và sau đó giết nhóm quy trình khi thất bại, nhưng bạn cũng muốn một stdin ở phía máy khách chặn cho đến khi quá trình phía máy chủ được thực hiện và sẽ không để lại các quy trình kéo dài như <( ngủ vô cùng) có thể.

ssh localhost "sleep 99 < <(cat; kill -INT 0)" <&1

Nó dường như không thực sự chuyển hướng thiết bị xuất chuẩn ở bất cứ đâu nhưng nó hoạt động như một đầu vào chặn và tránh bắt các tổ hợp phím.

Lỗi opensshant có liên quan: https://ormszilla.mindrot.org/show_orms.cgi?id=394#c14


0

Nếu bạn muốn vô hiệu hóa hành vi đó (dường như mặc định), bạn cần kích hoạt ssh-keep-live trên máy khách hoặc phía máy chủ.

Nếu bạn nhìn vào các tùy chọn ssh-keep-live-in trong các trang man, bạn có thể thấy rằng chúng bị tắt theo mặc định.


0

Câu trả lời của tôi dựa trên teru. Tôi cần một tập lệnh trợ giúp ~/helpertại máy chủ server.ip:

#!/bin/bash
TUBE=/tmp/sshCoLab_myfifo.$$;
mkfifo "$TUBE"
( <"$TUBE" "$@" ; rm "$TUBE" ; kill -TERM 0 ) &  
cat >"$TUBE" ;
rm "$TUBE" ;
kill -TERM 0 ;

Nếu nó được gọi là vd với

ssh server.ip ~/helper echo hello from server

và thực thi echo hello from servertại server.ip, và sau đó ssh client sẽ chấm dứt.

Nếu nó được gọi là vd với

ssh server.ip ~/helper sleep 1000 &
CHID=$!

kill -9 $CHIDcũng sẽ dừng tập lệnh tại máy chủ. Đối với tôi, kill -INT $CHIDkhông hoạt động, nhưng tôi không biết tại sao.

Trong câu trả lời của teru, lệnh ssh sẽ đợi mãi khi lệnh từ xa kết thúc, vì catkhông bao giờ kết thúc.

Tất cả các câu trả lời với ssh -t không hoạt động với tôi kill, mà chỉ với Ctrl-C.

Chỉnh sửa: Tôi phát hiện ra điều này hoạt động từ một Ubuntu 14.01 mới đến một hộp linux khoa học cũ - nhưng không phải là cách khác. Vì vậy, tôi nghĩ rằng không có giải pháp chung. Kỳ dị.

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.