Khước từ
Nếu kết nối SSH của bạn không tồn tại trong thời gian ngừng hoạt động mạng ngắn, thì có một điều khác xảy ra là không cho phép ssh
và TCP làm việc bình thường.
Xem bên dưới để biết chi tiết. Dù sao:
Giải pháp không phụ thuộc nhanh nhất và bẩn nhất
Tạo một kịch bản shell như thế này:
#!/bin/sh -
# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'
# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255
# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
ssh $timeout_options -t "$@" screen -dR
status=$?
# You can add a `sleep` command here or a counter or whatever
# you might need as far as rate/retry limiting.
done
exit "$status"
Điều này sẽ chỉ chạy một vòng lặp đơn giản ngu ngốc mà cố gắng kết nối ssh
và gắn vào screen
. Vượt qua máy chủ lưu trữ hoặc bất cứ điều gì khác mà bạn thường chuyển đến ssh
lời gọi của mình dưới dạng đối số dòng lệnh.
Việc kết nối lại chỉ dựa trên việc SSH có báo lỗi với kết nối hay không, điều đó có nghĩa là nó không có trí thông minh để phát hiện các lỗi không phải SSH như "bạn thực sự không bật WiFI" hay bất cứ điều gì, nhưng điều đó có lẽ không quan trọng bạn.
Tôi giả sử bạn có ssh-agent
hoặc một khóa SSH không có cụm mật khẩu sẽ cho phép kết nối lại chỉ hoạt động mà không cần thêm đầu vào từ bạn.
Sẽ có một điều kiện cuộc đua nhỏ mà nếu bạn đánh ^C
trong một phần không thể nhận ra của con người trong một giây trong khi kết nối lại, bạn có thể sẽ giết chết tập lệnh thay vì chuyển ^C
qua thiết bị đầu cuối của khách hàng, vì vậy nếu bạn nghi ngờ bị treo kết nối Đừng ^C
quá nhiệt tình.
Giải pháp phần mềm bổ sung đơn giản nhất
Bạn có thể thử các chương trình autossh , mà nên có sẵn trong kho gói Ubuntu của bạn.
Nếu bạn cần xây dựng từ nguồn hoặc kiểm toán nó, thì đó là một chương trình C duy nhất biên dịch mà không có bất kỳ thư viện bổ sung nào, dường như có nhiều thông tin hơn về việc kiểm tra sự sống động của kết nối so với hack của tôi ở trên và nó cũng có một rscreen
lệnh script thuận tiện tự động -cách để screen
.
Chi tiết
Làm thế nào ssh
bình thường phục hồi
Chỉ để xác minh, vì tôi không thích nói những điều mà không tự kiểm tra, tôi đã chạy thử một chút trước khi trả lời:
Tôi đã kết nối WiFi với thiết bị Linux, tạo kết nối SSH với thiết bị khác trong mạng LAN của mình, xác minh rằng tôi có ssh
kết nối hoạt động với đầu bên kia (có thể chạy các lệnh, v.v.), sau đó trên máy khách ngắt kết nối WiFi (gây ra giao diện để được định cấu hình: không có thêm địa chỉ IP), nhập thêm một loạt ký tự vào phiên ssh (tất nhiên không có phản hồi) và sau đó kết nối lại với WiFi của tôi - kết nối lại thực sự thất bại ít nhất một lần do tín hiệu xấu và các yếu tố khác , sau đó cuối cùng đã kết nối lại: Tôi đợi khoảng năm giây để ssh
phiên phục hồi, không có gì xảy ra nên tôi nhấn thêm một phím và ssh
phiên ngay lập tức trở lại, với tất cả các phím mà tôi đã gõ trong khi ngắt kết nối xuất hiện trên dòng lệnh.
Hãy xem, ssh
chỉ ghi / đọc vào ổ cắm mạng TCP cho đến khi HĐH báo lỗi, và TCP thực sự rất chịu đựng sự sụt giảm kết nối kéo dài.
Còn lại với các thiết bị của riêng nó với cài đặt kernel mặc định, ngăn xếp TCP trong Linux sẽ vui vẻ chấp nhận kết nối hoàn toàn im lặng trong nhiều phút trước khi tuyên bố kết nối bị chết và báo lỗi ssh
- đến lúc cuối cùng chúng ta nói chuyện trong sân bóng trong khoảng 30 phút, hoặc ít nhất là chắc chắn đủ lâu để tồn tại lâu hơn các trục trặc kết nối kéo dài một giây hoặc một phút.
Tuy nhiên, bên dưới vỏ bọc, ngăn xếp TCP TCP sẽ dần dần lấy lại các tin nhắn với độ trễ dài hơn và lâu hơn, điều đó có nghĩa là vào thời điểm kết nối của bạn quay trở lại, bạn có thể sẽ xem xét độ trễ bổ sung trước khi ssh
phiên của bạn dường như "sống lại".
Tại sao điều này đôi khi phá vỡ
Thường thì một cái gì đó đang tích cực khiến kết nối đóng lại sau một khoảng thời gian không hoạt động ngắn hơn đáng kể so với số lượng mà ngăn xếp TCP sẽ chịu đựng, và sau đó không báo cáo trạng thái kết nối đó cho ssh
khách hàng của bạn .
Các ứng viên có khả năng bao gồm:
Tường lửa hoặc bộ định tuyến NAT, phải sử dụng bộ nhớ để ghi nhớ từng kết nối TCP trực tiếp - như một tối ưu hóa và giảm thiểu chống lại các cuộc tấn công của DOS, đôi khi chúng sẽ quên kết nối của bạn và sau đó âm thầm bỏ qua các gói tin do đó, vì các gói trong ở giữa một kết nối khi bạn không nhớ kết nối hiện tại trông không hợp lệ.
Tường lửa / bộ định tuyến hoạt động tốt hơn sẽ tiêm gói TCP RST, thường biểu hiện dưới dạng connection reset by peer
thông báo lỗi, nhưng gói đặt lại là lỗi và do đó, nếu kết nối đến máy khách của bạn vẫn gặp sự cố tại thời điểm đó và làm mất đặt lại gói quá, khách hàng của bạn sẽ nghĩ rằng kết nối vẫn còn sống.
Bản thân máy chủ có thể có chính sách tường lửa để âm thầm loại bỏ các gói không mong muốn, điều này sẽ phá vỡ các nỗ lực nối lại kết nối của máy khách bất cứ khi nào máy chủ nghĩ rằng kết nối bị đóng nhưng máy khách thì không: máy khách của bạn tiếp tục cố gắng tiếp tục kết nối, nhưng máy chủ chỉ là bỏ qua nó bởi vì không có kết nối trực tiếp mà các gói này thuộc về trạng thái tường lửa của máy chủ.
Vì bạn đang chạy Linux, hãy kiểm tra cẩn thận máy chủ của bạn iptables
/ ip6tables
(hoặc nft
nếu bạn đang sử dụng công cụ mới) để biết chính xác những gì bạn cho phép so với việc bỏ. Việc cho phép các gói mới / thành lập / liên quan trên cổng TCP SSH, nhưng không phổ biến là rất phổ biến - nếu bạn bỏ âm thầm mọi thứ không được phép, thiết lập chung này có thể gây ra các loại đóng băng này sau các sự cố kết nối ngắn .
Bản thân máy chủ SSH của bạn có thể được cấu hình để đóng kết nối sau một thời gian không hoạt động, sử dụng một trong các tùy chọn OpenSSH cho các gói giữ lại máy khách TCP hoặc SSH. Chính nó, điều này sẽ không gây ra treo cổ vô thời hạn, nhưng nó có thể đưa bạn vào một trong những trạng thái được mô tả ở trên.
Có thể bạn chỉ không dành đủ thời gian để "gỡ rối" sau khi bạn vào trạng thái nơi ssh
phiên của bạn bị treo.
<Enter>
và gõ~.
để yêu cầu phía bạn bỏ kết nối và bạn chỉ cần lặp lại lệnh ssh cuối cùng để kết nối lại (ví dụ: với mũi tên lên hoặc!!
).