Giả sử của bạn rằng ssh
chính nó trả về trạng thái thoát 255 là chính xác. Các ssh
trang người đàn ông khẳng định rằng:
ssh thoát với trạng thái thoát của lệnh từ xa hoặc với 255 nếu xảy ra lỗi.
Nếu bạn chỉ đơn giản là chạy ssh pi@10.20.0.10 "pkill -f asdf"
, rất có thể bạn sẽ nhận được trạng thái thoát 1
, tương ứng với pkill
trạng thái cho Không có quy trình nào khớp với .
Phần thử thách là để hiểu tại sao xảy ra lỗi với SSH khi bạn chạy
ssh pi@10.20.0.10 "pkill -f asdf || true"
Các lệnh từ xa SSH
Máy chủ SSH khởi chạy shell để chạy (các) lệnh từ xa. Đây là một ví dụ về điều này trong hành động:
$ ssh server "ps -elf | tail -5"
4 S root 35323 1024 12 80 0 - 43170 poll_s 12:01 ? 00:00:00 sshd: anthony [priv]
5 S anthony 35329 35323 0 80 0 - 43170 poll_s 12:01 ? 00:00:00 sshd: anthony@notty
0 S anthony 35330 35329 0 80 0 - 28283 do_wai 12:01 ? 00:00:00 bash -c ps -elf | tail -5
0 R anthony 35341 35330 0 80 0 - 40340 - 12:01 ? 00:00:00 ps -elf
0 S anthony 35342 35330 0 80 0 - 26985 pipe_w 12:01 ? 00:00:00 tail -5
Lưu ý rằng shell mặc định là bash
và lệnh từ xa không phải là một lệnh đơn giản mà là một đường ống , một chuỗi gồm một hoặc nhiều lệnh được phân tách bởi toán tử điều khiển |
.
Shell Bash đủ thông minh để nhận ra rằng nếu lệnh được truyền cho nó bởi -c
tùy chọn là một lệnh đơn giản , nó có thể tối ưu hóa bằng cách không thực sự tạo ra một quy trình mới, tức là, nó trực tiếp exec
là lệnh đơn giản thay vì đi qua bước bổ sung của fork
ing trước khi nó exec
s. Đây là một ví dụ về những gì xảy ra khi bạn chạy một lệnh đơn giản từ xa ( ps -elf
trong trường hợp này):
$ ssh server "ps -elf" | tail -5
1 S root 34740 2 0 80 0 - 0 worker 11:49 ? 00:00:00 [kworker/0:1]
1 S root 34762 2 0 80 0 - 0 worker 11:50 ? 00:00:00 [kworker/0:3]
4 S root 34824 1024 31 80 0 - 43170 poll_s 11:51 ? 00:00:00 sshd: anthony [priv]
5 S anthony 34829 34824 0 80 0 - 43170 poll_s 11:51 ? 00:00:00 sshd: anthony@notty
0 R anthony 34830 34829 0 80 0 - 40340 - 11:51 ? 00:00:00 ps -elf
Tôi đã gặp phải hành vi này trước đây nhưng tôi không thể tìm thấy một tài liệu tham khảo nào tốt hơn câu trả lời AskUb Ubuntu này .
hành vi của pkill
Vì pkill -f asdf || true
không phải là một lệnh đơn giản (nó là một danh sách lệnh ), nên việc tối ưu hóa ở trên không thể xảy ra nên khi bạn chạy ssh pi@10.20.0.10 "pkill -f asdf || true"
, sshd
tiến trình sẽ chuyển đổi và thực thi bash -c "pkill -f asdf || true"
.
Như câu trả lời của ctx chỉ ra, pkill
sẽ không giết quá trình của chính nó. Tuy nhiên, nó sẽ giết bất kỳ tiến trình nào khác có dòng lệnh khớp với -f
mẫu. Các bash -c
lệnh phù hợp với mô hình này để nó giết chết quá trình này - cha mẹ của mình (vì nó xảy ra).
Sau đó, máy chủ SSH thấy rằng tiến trình shell mà nó khởi động để chạy các lệnh từ xa đã bị giết một cách bất ngờ nên nó báo lỗi cho máy khách SSH.
pkill
giết chết quá trình shell mẹ của nó bởi vì danh sách arg của nó phù hợp với regexp, tôi sẽ nâng cao một sự phản đối thuật ngữ:x || y
là không một lệnh phức hợp , đó là một danh sách lệnh .