MXterm Pro

Cách chặn SSH bị ngắt kết nối trên MacBook bằng keepalive

Henry AGI
5 phút đọc
File ssh config với Host *, ServerAliveInterval 60 và ServerAliveCountMax 3, chú thích gửi gói mỗi 60 giây và bỏ cuộc sau 180 giây

Để chặn SSH timeout trên MacBook, hãy thêm ServerAliveInterval 60 và ServerAliveCountMax 3 vào khối Host * trong ~/.ssh/config. Khi đó SSH client trên Mac sẽ gửi một gói tin keepalive nhỏ trước khi router Wi-Fi, firewall công ty hoặc bộ đếm idle của máy chủ kịp đóng kết nối. Tuy nhiên, cách này không giúp phiên sống sót qua sleep hay khi đổi Wi-Fi. Phần dưới sẽ chỉ ra bạn đang gặp loại timeout nào trong bốn loại.

Đặt SSH keepalive toàn cục trong ~/.ssh/config

Mở (hoặc tạo) ~/.ssh/config rồi thêm khối Host * với hai directive: ServerAliveInterval 60 và ServerAliveCountMax 3. Các ứng dụng terminal chạy shell của bạn, kể cả MXterm Pro, đều dùng lệnh ssh trong PATH, thường là OpenSSH đi kèm macOS.

Từ giờ SSH client gửi một gói tin rỗng kiểu "bạn còn đó không" tới máy chủ mỗi 60 giây. Nếu ba gói liên tiếp (180 giây) không được trả lời, SSH đóng kết nối gọn gàng thay vì treo trên một socket đã chết.

Đặt khối Host * bao trùm ở cuối file. OpenSSH dùng quy tắc "giá trị đầu tiên nhận được sẽ thắng" cho từng tùy chọn. Nếu bạn đã có các khối Host riêng cho từng máy chủ (một jump host, một máy VPN công ty có cấu hình riêng), khối Host * nằm phía trên chúng đã "chiếm" ServerAliveInterval trước khi khối riêng được đọc.

Với khoảng cách 60 giây và 3 lần thử, SSH mất tối đa ba phút để nhận ra kết nối đã chết, đây là điểm khởi đầu hợp lý. Nếu firewall công ty hoặc Wi-Fi công cộng cắt các kết nối idle quanh mốc một phút, hãy giảm xuống ServerAliveInterval 30 và ServerAliveCountMax 2. Bạn phát hiện kết nối rớt sau một phút thay vì ba phút, đổi lại là thêm một gói tin nhỏ mỗi 30 giây.

Để xác nhận nó hoạt động, hãy để một phiên idle lâu hơn khoảng thời gian từng làm nó bị ngắt, rồi kiểm tra phiên còn đó không. Phần FAQ bên dưới chỉ cách theo dõi chính các gói tin keepalive.

SSH client của macOS mặc định đã bật TCPKeepAlive yes, nhưng đó là kiểm tra ở tầng TCP và có thể mất tới hai giờ mới nhận ra một socket thực sự đã chết. Nó không giúp gì trước firewall hay thiết bị NAT vẫn chuyển tiếp gói tin nhưng đã coi kết nối idle của bạn là kết thúc. ServerAliveInterval thì hoạt động ở tầng giao thức SSH, nên đây mới là tùy chọn xử lý được chuyện này.

Bài liên quanCách quản lý 50+ server Linux và VM cloud từ một máy Mac

Bạn đang gặp loại timeout nào (và vì sao MacBook dễ dính hơn)

Không phải lần ngắt SSH nào cũng cùng nguyên nhân, và cách sửa đúng phụ thuộc vào việc bạn gặp loại nào.

Timeout do firewall hoặc NAT khi idle: một thiết bị nằm giữa bạn và máy chủ (firewall công ty, router ở nhà, cổng VPN) coi kết nối không có lưu lượng trong vài phút là đã chết và xóa trạng thái của nó. ServerAliveInterval xử lý thẳng trường hợp này, miễn là giá trị nhỏ hơn cửa sổ timeout của thiết bị đó.

Timeout idle phía máy chủ: sshd từ xa được cấu hình để ngắt các client idle, hoặc login shell có TMOUT riêng. ServerAliveInterval ở máy bạn giúp được trường hợp sshd, vì client của bạn không còn trông như idle từ phía máy chủ.

Đổi mạng: chuyển sang mạng Wi-Fi khác, bật VPN hoặc di chuyển giữa nhà và hotspot sẽ làm đổi IP giữa chừng phiên. Kết nối TCP của SSH không sống sót qua việc đó, và không tùy chọn keepalive nào sửa được chuyện đổi IP. Chỉ một giao thức được thiết kế cho việc này (Mosh) mới làm được, và nó đánh đổi một số tính năng terminal để lấy độ bền kết nối đó.

Sleep: loại đặc thù của MacBook. Khi bạn đóng nắp hoặc Mac vào trạng thái sleep, máy ngừng chạy SSH client, nên không có gói tin keepalive nào được gửi đi trong khoảng đó. Khi máy thức dậy, máy chủ thường đã bỏ kết nối và SSH báo timeout hoặc broken pipe.

Nếu một phiên phải sống sót khi đóng nắp máy, hãy chạy job từ xa bên trong tmux/screen để job không bị ảnh hưởng khi kết nối cục bộ rớt (xem thêm ở phần FAQ).

Sửa cả phía máy chủ (ClientAliveInterval trong sshd_config) nếu có thể

Nếu bạn quản lý máy chủ từ xa, bạn cũng có thể chặn SSH timeout từ phía đó. Thêm ClientAliveInterval 60 và ClientAliveCountMax 3 vào /etc/ssh/sshd_config rồi restart sshd. Đây là bản đối xứng phía máy chủ của tùy chọn bên client, và nó ngăn máy chủ trở thành bên ngắt kết nối với bạn.

Nếu bạn không kiểm soát máy chủ (shared host, VM của khách hàng, máy cloud do người khác quản lý), bạn vẫn không bị kẹt. ServerAliveInterval trong ~/.ssh/config của chính bạn hoạt động độc lập, vì client của bạn gửi lưu lượng keepalive và sshd từ xa không cần phối hợp.

Chuyện gì xảy ra trong MXterm Pro khi phiên SSH bị timeout

Mỗi terminal pane trong MXterm Pro là một PTY thật chạy login shell bình thường của bạn, xây dựng trên Tauri với portable-pty viết bằng Rust. Đó không phải một tab trình duyệt giả làm terminal.

Kết nối SSH bạn mở trong đó dùng chính OpenSSH client mà Mac của bạn đã có sẵn. Trong một pane thường, ssh đọc ~/.ssh/config của bạn y hệt như trong Terminal.app hoặc iTerm2, nên các dòng keepalive trong hướng dẫn này áp dụng nguyên vẹn.

Pane mở từ một host đã lưu thì khác. MXterm Pro khởi chạy ssh với -o ServerAliveInterval=30 -o ServerAliveCountMax=3 ngay trên dòng lệnh, nên nó nhận ra kết nối chết sau khoảng 90 giây. OpenSSH lấy giá trị đầu tiên nhận được, và tùy chọn trên dòng lệnh đứng trước file cấu hình. Vì vậy các giá trị trong ~/.ssh/config của bạn cho hai tùy chọn đó không áp dụng cho pane này.

Bạn thấy gì khi phiên rớt còn tùy cách bạn mở nó. Nếu tự gõ ssh vào một pane thường, tiến trình thoát là ssh, không phải shell bên dưới. Bạn quay về prompt cục bộ của Mac ngay trong pane đó, mọi thứ đã in ra vẫn còn trên màn hình. Để kết nối lại, gõ lại lệnh hoặc bấm ↑.

Pane mở từ host đã lưu hành xử khác. Nó chạy thẳng ssh nên không có shell nào để quay về. Với mã thoát 255 mà một phiên rớt thường trả về, pane tự in một dòng chữ mờ bắt đầu bằng SSH connection failed or dropped (exit 255) và kết thúc bằng press Enter to reconnect. Bấm Enter để mở lại kết nối.

Với bất kỳ mã thoát nào khác, pane in Disconnected (exit N) rồi tới press Enter to reconnect.

SSH Host Manager (⌘⇧H) giúp ở trước và sau một lần rớt chứ không phải ngay trong lúc nó xảy ra. Kết nối qua host đã lưu tái dùng cơ chế connection multiplexing của chính OpenSSH (ControlMaster=auto, ControlPersist=10m). Sau đó, mở panel file SFTP cho một host bạn đã kết nối sẽ tái dùng kết nối đó và bỏ qua bước handshake. Kết nối dùng chung vẫn mở thêm 10 phút sau khi phiên cuối cùng trên nó đóng. Thêm về host đã lưu có trong tài liệu SSH và SFTP.

Kết nối dùng chung sẽ đóng sớm hơn nếu bạn đổi cài đặt kết nối của host đã lưu hoặc xóa host, và panel file có nút Đặt lại kết nối cho server từ chối đăng nhập hoặc bắt đổi mật khẩu.

Một ghi chú về gói cho ai quản lý nhiều hơn vài máy chủ: mặc định gói Free lưu tối đa 5 SSH host trong trình quản lý đó, còn gói Pro trả phí thì bỏ mức trần này.

So sánh MXterm Pro với iTerm2, Warp, Termius và MobaXterm cho phiên SSH dài

Termius hỗ trợ Mosh, thứ sống sót được qua đổi IP và sleep/wake theo cách mà SSH thuần về cấu trúc không làm được. Muốn so sánh đầy đủ hơn, xem các SSH client tốt nhất cho Mac.

MXterm Pro chạy song song nhiều phiên SSH cùng các AI coding agent (Claude Code, Codex, Gemini CLI) trong một workspace. Khi bạn tick chọn tùy chọn cô lập worktree trong composer của tab mới (tắt mặc định, chỉ áp dụng cho git repo), mỗi agent pane có git worktree riêng, giúp giảm khả năng thay đổi của agent này xung đột với agent khác. Nó không thay thế các tùy chọn keepalive ở trên, nên hãy đặt chúng dù bạn dùng ứng dụng terminal nào.

Trải nghiệm ngay

Terminal đa pane, Command Recipes (Cmd+J), và Control Room (trước đây là War Room) đa agent: miễn phí để bắt đầu.

Tải MXterm Pro Miễn Phí

Đã có MXterm Pro? Đọc hướng dẫn cài đặt →

Chưa dùng MXterm Pro? Xem bảng giá →

Câu hỏi thường gặp

ServerAliveInterval và ClientAliveInterval khác nhau thế nào?

ServerAliveInterval là tùy chọn phía client, đặt trong ~/.ssh/config trên chính Mac của bạn. Nó bảo máy của bạn ping máy chủ. ClientAliveInterval là bản đối xứng phía máy chủ, đặt trong /etc/ssh/sshd_config trên máy từ xa. Nó bảo máy chủ ping client của bạn. Bạn chỉ cần một phía là keepalive hoạt động. Đặt cả hai cũng không hại gì, và hữu ích khi bạn chưa chắc đầu nào đang timeout.

Có nên chạy job dài trong tmux hoặc screen thay vì dựa vào keepalive không?

Có, với bất cứ thứ gì phải sống sót qua một lần ngắt kết nối thật sự, không chỉ timeout idle. ServerAliveInterval chỉ ngăn kết nối bị giết vì trông có vẻ idle. Nó không cứu được job nếu MacBook sleep, Wi-Fi rớt hoặc bạn đóng nắp máy. Một build hoặc migration chạy trong tmux hay screen trên máy chủ từ xa vẫn chạy tiếp dù kết nối cục bộ ra sao. Gắn lại bằng tmux attach khi bạn online trở lại.

Tại sao đã đặt ServerAliveInterval mà SSH vẫn bị timeout?

Thường là vì MacBook đã sleep, không phải vì keepalive hỏng. Mac đang sleep không chạy SSH client nào, nên không có gói tin keepalive nào được gửi đi. SSH báo lỗi rớt kết nối ngay khi bạn đánh thức máy.

Làm sao kiểm tra keepalive SSH có đang hoạt động không?

Cách đơn giản nhất là để một phiên idle lâu hơn khoảng thời gian từng làm nó bị ngắt, rồi xác nhận phiên vẫn còn. Để xem chính các gói tin, chạy sudo tcpdump -i en0 host <server-ip> and port 22 trong một cửa sổ thứ hai. Theo dõi các gói tin nhỏ được gửi đi cứ mỗi ServerAliveInterval giây, kể cả khi phiên đang idle. Pane mở từ host đã lưu thì gửi chúng mỗi 30 giây.

Hỏi AI về MXterm Pro

Mở câu trả lời trực tiếp trong ChatGPT, Claude hoặc Perplexity, dựa trên trang này. Trợ lý AI tự viết, không phải chúng tôi, nên hãy kiểm tra nguồn nó trích dẫn.

Câu hỏi được gửiLàm sao để kết nối SSH không bị ngắt trên MacBook, và ServerAliveInterval với ServerAliveCountMax làm gì?