Việc ngắt kết nối từ phiên SSH có làm hỏng chương trình của bạn không?


88

Vì vậy, nói tôi bị ngắt kết nối từ một SSH-session sau khi tôi đã bắt đầu rsynchoặc cphoặc bất kỳ lệnh khác mà có thể dài chạy. Lệnh đó có tiếp tục chạy cho đến khi nó kết thúc sau khi tôi bị ngắt kết nối hay nó bị giết?

Luôn tự hỏi điều này.


Tôi chỉ muốn thêm vào những gì đã nói ở trên rằng, nếu bạn thấy mình trong một tình huống khi bạn cần đặt một quy trình đã chạy vào screen, hãy thử reptyr .
một anh chàng buồn bã

Nó sẽ giết chương trình của bạn. Rất khó chịu nếu bạn đang cập nhật phiên bản HĐH từ Ubuntu 16.04 đến 17.10 thông qua SSH
Kurdtpage

Câu trả lời:


118

Chỉnh sửa cho năm 2016:

Câu hỏi và trả lời này trước sự kiện systemd v230 . Kể từ systemd v230, mặc định mới là giết tất cả trẻ em của một phiên đăng nhập chấm dứt, bất kể các biện pháp phòng ngừa hợp lệ trong lịch sử đã được thực hiện để ngăn chặn điều này. Các hành vi có thể được thay đổi bằng cách thiết lập KillUserProcesses=notrong /etc/systemd/logind.conf, hoặc phá vỡ bằng cách sử dụng cơ chế systemd cụ thể để bắt đầu một daemon trong userspace. Những cơ chế nằm ngoài phạm vi của câu hỏi này.

Văn bản dưới đây mô tả cách mọi thứ hoạt động theo truyền thống trong không gian thiết kế UNIX lâu hơn Linux đã tồn tại.


Họ sẽ bị giết, nhưng không nhất thiết phải ngay lập tức. Nó phụ thuộc vào thời gian để trình nền SSH mất bao lâu để quyết định rằng kết nối của bạn đã chết. Những gì tiếp theo là một lời giải thích dài hơn sẽ giúp bạn hiểu làm thế nào nó thực sự hoạt động.

Khi bạn đăng nhập, trình nền SSH đã cấp phát một thiết bị đầu cuối giả cho bạn và gắn nó vào vỏ đăng nhập được cấu hình của người dùng của bạn. Đây được gọi là thiết bị đầu cuối kiểm soát. Mỗi chương trình bạn bắt đầu bình thường tại thời điểm đó, bất kể có bao nhiêu lớp vỏ sâu, cuối cùng sẽ theo dõi tổ tiên của nó trở lại lớp vỏ đó. Bạn có thể quan sát điều này với pstreelệnh.

Khi quy trình SSH daemon được liên kết với kết nối của bạn quyết định rằng kết nối của bạn đã chết, nó sẽ gửi tín hiệu gác máy ( SIGHUP) đến vỏ đăng nhập. Điều này thông báo cho lớp vỏ mà bạn đã biến mất và nó sẽ bắt đầu tự dọn sạch. Điều xảy ra tại thời điểm này là shell cụ thể (tìm kiếm trang tài liệu của nó cho "HUP"), nhưng đối với hầu hết các phần, nó sẽ bắt đầu gửi SIGHUPđến các công việc đang chạy liên quan đến nó trước khi chấm dứt. Lần lượt, mỗi quá trình đó sẽ làm bất cứ điều gì chúng được cấu hình để thực hiện khi nhận được tín hiệu đó. Thông thường có nghĩa là chấm dứt. Nếu những công việc đó có công việc của riêng họ, tín hiệu cũng sẽ thường được truyền qua.

Các quy trình tồn tại trong trạng thái treo của thiết bị đầu cuối điều khiển là các quy trình tự tách rời khỏi thiết bị đầu cuối (quy trình daemon mà bạn đã bắt đầu bên trong thiết bị đầu cuối) hoặc các quy trình được gọi bằng nohuplệnh có tiền tố . (tức là "không treo lên này") Daemon diễn giải tín hiệu HUP khác nhau; vì chúng không có thiết bị đầu cuối điều khiển và không tự động nhận tín hiệu HUP, thay vào đó, nó được gửi lại theo yêu cầu thủ công từ quản trị viên để tải lại cấu hình. Trớ trêu thay điều này có nghĩa là hầu hết các quản trị viên không học cách sử dụng "gác máy" của tín hiệu này cho những người không phải daemon cho đến nhiều, rất nhiều sau đó. Đó là lý do tại sao bạn đọc nó!

Bộ ghép kênh đầu cuối là một cách phổ biến để giữ cho môi trường vỏ của bạn nguyên vẹn giữa các lần ngắt kết nối. Chúng cho phép bạn tách ra khỏi các quy trình hệ vỏ của mình theo cách mà bạn có thể gắn lại cho chúng sau này, bất kể việc ngắt kết nối đó là vô tình hay cố ý. tmuxscreenlà những người phổ biến hơn; cú pháp sử dụng chúng nằm ngoài phạm vi câu hỏi của bạn, nhưng chúng đáng để xem xét.


Tôi đã yêu cầu tôi giải thích về việc mất bao lâu để trình nền SSH quyết định rằng kết nối của bạn đã chết. Đây là một hành vi dành riêng cho mọi triển khai của trình nền SSH, nhưng bạn có thể tin tưởng vào tất cả chúng để chấm dứt khi một trong hai bên đặt lại kết nối TCP. Điều này sẽ xảy ra nhanh chóng nếu máy chủ cố gắng ghi vào ổ cắm và các gói TCP không được xác nhận hoặc chậm nếu không có gì đang cố ghi vào PTY.

Trong bối cảnh cụ thể này, các yếu tố có khả năng kích hoạt ghi là:

  • Một quá trình (thường là một trong nền trước) cố gắng ghi vào PTY ở phía máy chủ. (máy chủ-> khách hàng)
  • Người dùng cố gắng ghi vào PTY ở phía máy khách. (khách hàng-> máy chủ)
  • Keepalives của bất kỳ loại. Chúng thường không được bật theo mặc định, bởi máy khách hoặc máy chủ và thường có hai hương vị: cấp độ ứng dụng và dựa trên TCP (nghĩa là SO_KEEPALIVE). Số tiền giữ cho máy chủ hoặc máy khách không thường xuyên gửi các gói đến phía bên kia, ngay cả khi không có lý do gì để ghi vào ổ cắm. Mặc dù điều này thường nhằm khắc phục các tường lửa hết thời gian kết nối quá nhanh, nhưng nó có thêm tác dụng phụ khiến người gửi chú ý khi phía bên kia không phản hồi nhanh hơn nhiều.

Các quy tắc thông thường cho các phiên TCP được áp dụng ở đây: nếu có sự gián đoạn trong kết nối giữa máy khách và máy chủ, nhưng không bên nào cố gắng gửi gói trong khi xảy ra sự cố, kết nối sẽ tồn tại với điều kiện cả hai bên đều phản ứng nhanh và nhận được TCP dự kiến số thứ tự.

Nếu một bên đã quyết định rằng ổ cắm đã chết, các hiệu ứng thường ngay lập tức: quá trình sshd sẽ gửi HUPvà tự chấm dứt (như được mô tả trước đó), hoặc khách hàng sẽ thông báo cho người dùng về sự cố được phát hiện. Điều đáng chú ý là chỉ vì một bên nghĩ rằng bên kia đã chết không có nghĩa là bên kia đã được thông báo về việc này. Phần mồ côi của kết nối thường sẽ vẫn mở cho đến khi nó cố gắng ghi vào nó và hết thời gian, hoặc nhận được thiết lập lại TCP từ phía bên kia. (nếu kết nối có sẵn tại thời điểm đó) Việc dọn dẹp được mô tả trong câu trả lời này chỉ xảy ra khi máy chủ nhận thấy.


3
Tôi cũng đã thêm lệnh 'dtach' vào danh sách đó - nó trái ngược với màn hình / tmux ở chỗ nó cho phép bạn gắn nhiều thiết bị đầu cuối vào một phiên duy nhất và cũng rất tuyệt để kéo dài một phiên, mặc dù nó không cung cấp bất kỳ phương tiện phát lại lịch sử gần đây.
lông mịn

dtachurl ở đây: dtach.sourceforge.net
slm

2
giải thích tuyệt vời. Tôi cảm thấy nhiều linuxey hơn!
fregas

3
Ngoài ra, mặc dù về mặt kỹ thuật không phải là một phần trong câu trả lời của bạn, đây là một câu đố nhỏ thú vị: bạn có thể sử dụng kill -HUPnhư root để buộc thiết bị đầu cuối của ai đó bị treo. Bạn không nên làm điều này mà không có lý do chính đáng. Tôi nhận được hầu hết số dặm của mình khi người dùng để shell chạy trong quá trình bảo trì và tôi cần ngắt kết nối một hệ thống tập tin mà trình bao của họ đang mở. Nếu người dùng được kết nối nhưng không hoạt động, hãy gửi tín hiệu đến quy trình sshd của họ. Mặt khác, nếu nó chạy bên trong bộ ghép kênh đầu cuối, hãy gửi nó đến trình bao bạn muốn dừng. Chỉ treo vỏ giữ bạn làm việc!
Andrew B

@AndrewB, bạn có thể giải thích rõ hơn về cách "quy trình SSH daemon ... quyết định rằng kết nối của bạn đã chết" không? Và làm thế nào tôi có thể biết nếu daemon SSH nghĩ / biết rằng kết nối (mà) đã chết hay không?
Xiao Peng - ZenUML.com

22

Như những người khác đã đề cập, một khi bạn ngắt kết nối với ssh, mọi thứ đang chạy trong đó sẽ biến mất.

Như @Michael Hampton và những người khác đã đề cập, bạn có thể sử dụng các công cụ như tmuxhoặc screenngắt kết nối / kết nối lại với các thiết bị đầu cuối mà không mất nội dung của chúng (tức là các quy trình con).

Ngoài ra, bạn có thể đặt một quá trình vào nền bằng cách sử dụng ký hiệu &và sau đó sử dụng lệnh disownđể phân tách chúng với trình bao hiện tại.

# start a command
% sleep 5000 &
[1] 3820

# check it
% jobs
[1]+  Running                 sleep 5000 &

# disown everything
% disown -a

# check it again (gone from shell)
% jobs
%

# but it's still running on the system
% ps -eaf|grep "[s]leep"
saml      3820 23791  0 00:16 pts/1    00:00:00 sleep 5000
%

Có thể gắn lại một phiên thiết bị đầu cuối vào một disownquy trình ed?
Tên giả

4
Đúng. Xem câu hỏi về U & L này để biết chi tiết: unix.stackexchange.com/questions / 4034 / Um
slm

13

Không, bất kỳ chương trình nào vẫn được gắn vào thiết bị đầu cuối và không được đặt vào nền với thứ gì đó giống như nohupsẽ bị giết.

Đây là lý do tại sao có các giải pháp thiết bị đầu cuối ảo như tmuxvà cũ hơn screentạo ra các phiên tiếp tục chạy ngay cả khi bạn bị ngắt kết nối và bạn có thể gắn lại sau nà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.