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 rsync
hoặc cp
hoặ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.
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 rsync
hoặc cp
hoặ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.
Câu trả lời:
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=no
trong /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 pstree
lệ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 nohup
lệ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ố ý. tmux
và screen
là 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à:
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 HUP
và 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.
dtach
url ở đây: dtach.sourceforge.net
kill -HUP
như 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!
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ư tmux
hoặc screen
ngắ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
%
disown
quy trình ed?
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ư nohup
sẽ 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ư tmux
và cũ hơn screen
tạ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.
screen
, hãy thử reptyr .