Giữ một quá trình linux chạy sau khi tôi đăng xuất


142

Tôi đang kết nối với máy Linux thông qua SSH và tôi đang cố chạy một tập lệnh bash nặng để thực hiện các hoạt động của hệ thống tệp. Dự kiến ​​sẽ tiếp tục chạy trong nhiều giờ, nhưng tôi không thể để phiên SSH mở vì các sự cố kết nối internet mà tôi gặp phải.

Tôi nghi ngờ rằng việc chạy tập lệnh với toán tử nền, ampersand ( &), sẽ thực hiện thủ thuật này, vì tôi đã thử nó và sau đó thấy rằng quá trình đó chưa hoàn thành. Làm thế nào tôi có thể đăng xuất và giữ cho quá trình chạy?

Câu trả lời:


135

Phương pháp tốt nhất là bắt đầu quá trình trong bộ ghép kênh đầu cuối. Ngoài ra, bạn có thể làm cho quá trình không nhận được tín hiệu HUP.


Bộ ghép kênh đầu cuối cung cấp các thiết bị đầu cuối "ảo" chạy độc lập với thiết bị đầu cuối "thực" (thực ra tất cả các thiết bị đầu cuối ngày nay là "ảo" nhưng đó là một chủ đề cho một ngày khác). Thiết bị đầu cuối ảo sẽ tiếp tục chạy ngay cả khi thiết bị đầu cuối thực sự của bạn được đóng bằng phiên ssh của bạn.

Tất cả các quy trình bắt đầu từ thiết bị đầu cuối ảo sẽ tiếp tục chạy với thiết bị ảo đó. Khi bạn kết nối lại với máy chủ, bạn có thể kết nối lại với thiết bị đầu cuối ảo và mọi thứ sẽ như không có gì xảy ra, ngoài thời gian đã qua.

Hai bộ ghép kênh đầu cuối phổ biến là màn hìnhtmux .

Màn hình có một đường cong học tập dốc. Dưới đây là một hướng dẫn tốt với các sơ đồ giải thích khái niệm: http://www.ibm.com/developerworks/aix/l Library / au-recu_screen /


Các HUP tín hiệu (hoặc SIGHUP) được gửi bởi nhà ga cho tất cả các tiến trình con của nó khi nhà ga được đóng lại. Hành động chung khi nhận SIGHUP là chấm dứt. Do đó, khi phiên ssh của bạn bị ngắt kết nối, tất cả các quy trình của bạn sẽ chấm dứt. Để tránh điều này, bạn có thể làm cho các quy trình của mình không nhận được SIGHUP.

Hai phương pháp dễ dàng để làm như vậy là nohupdisown.

Để biết thêm thông tin về cách thức nohupdisowncông việc, hãy đọc câu hỏi và câu trả lời này: https://unix.stackexchange.com/questions/3886/difference-b between-nohup-disown- and

Lưu ý: mặc dù các quy trình sẽ tiếp tục chạy nhưng bạn không thể tương tác với chúng nữa vì chúng không còn được gắn vào bất kỳ thiết bị đầu cuối nào. Phương pháp này chủ yếu hữu ích cho các quy trình hàng loạt chạy dài, một khi đã bắt đầu, không còn cần bất kỳ đầu vào nào của người dùng.


3
Tôi thích câu trả lời này vì nó cung cấp một giải pháp cho cả tình huống tương tác và không tương tác. Trong trường hợp tương tác, screencung cấp cho bạn nhiều tùy chọn hơn, nhưng nếu bạn đang sử dụng authorized_keysđể cho phép mọi người chạy tập lệnh từ xa ssh, thì nohuptùy chọn này là một cách đơn giản để kịch bản bắt đầu các quy trình kéo dài hơn sshphiên được sử dụng để khởi động chúng .
Đánh dấu gian hàng

1
@rahmanisback - Hãy nhớ rằng bạn có thể thay đổi câu trả lời được chấp nhận của mình bất cứ lúc nào. Chỉ vì cho đến nay câu trả lời của EricA được bình chọn nhiều nhất không có nghĩa đó là câu trả lời tốt nhất cho bạn, thực sự làm cho câu trả lời được chấp nhận của bạn có thể khuyến khích nhiều người bỏ phiếu như một câu trả lời hay.
Đánh dấu gian hàng

3
* ho * tmuxisbetter * ho *
crasic

3
màn hình> tmux . Hãy thử nó, bạn sẽ không bao giờ quay trở lại.
h0tw1r3

1
@TheLQ - byobu Màn hình GNU. Bạn vẫn đang sử dụng màn hình, chỉ với một .screenrc tùy biến cao.
EEAA

92

Có một vài cách để làm điều này, nhưng cách tôi thấy hữu ích nhất là sử dụng GNU Screen .

Sau khi bạn ssh vào, chạy screen. Điều này sẽ bắt đầu một shell khác chạy trong màn hình. Chạy lệnh của bạn, sau đó làm một Ctrl- a d.

Điều này sẽ "ngắt kết nối" bạn khỏi phiên màn hình. Tại thời điểm này, bạn có thể đăng xuất hoặc làm bất cứ điều gì bạn muốn.

Khi bạn muốn kết nối lại với phiên màn hình, chỉ cần chạy screen -RDtừ dấu nhắc shell (giống như người dùng sử dụng đã tạo phiên).


6
Màn hình có cả đống lệnh, tất cả bắt đầu bằng Ctrl-a. Nếu bạn chỉ học thêm một, hãy bắt đầu với "Ctrl-a?". Sau đó, bạn sẽ không học "Ctrl-a c" và "Ctrl-a n"
olafure

@olafure +1, cảm ơn. Có vẻ như Screen sẽ là hộp công cụ chính của tôi.
doc_id

màn hình> tmux . Hãy thử nó, bạn sẽ không bao giờ quay trở lại.
h0tw1r3

+1 cho tmux. Tôi đã từ bỏ màn hình 5 tuần trước.
Bryan Hunt

73

Trong bash, disowntừ khóa là hoàn toàn phù hợp với điều này. Đầu tiên, chạy quy trình của bạn trong nền (sử dụng &hoặc ^Zsau đó nhập bg):

$ wget --quiet http://server/some_big_file.zip &
[1] 1156

Bằng cách gõ, jobsbạn có thể thấy rằng quy trình vẫn thuộc sở hữu của trình bao:

$ jobs
[1]+  Running  wget

Nếu bạn đăng xuất vào thời điểm này, tác vụ nền cũng sẽ bị giết. Tuy nhiên, nếu bạn chạy disown, bash sẽ tách công việc và cho phép nó tiếp tục chạy:

$ disown

Bạn có thể xác nhận điều này:

$ jobs
$ logout

Bạn thậm chí có thể kết hợp &disowntrên cùng một dòng, như:

$ wget --quiet http://server/some_big_file.zip & disown
$ logout

Điều này tốt hơn so với việc chạy nohuptheo ý kiến ​​của tôi bởi vì nó không để lại nohup.outcác tệp nằm rải rác trên hệ thống tệp của bạn. Ngoài ra, nohupphải được chạy trước khi bạn chạy lệnh - disowncó thể được sử dụng nếu bạn chỉ quyết định sau đó về việc bạn muốn làm nền và tách nhiệm vụ.


1
Đó là một câu trả lời rất hay, 1+. Ưu tiên duy nhất cho nohup hoặc Screen sẽ là tính độc lập của bash và có thể được sử dụng với shell khác. Nhưng tôi sẽ theo cách tiếp cận của bạn bất cứ khi nào tôi đang sử dụng bash.
doc_id

Có - đây là đặc thù của bash, vì bash là vỏ duy nhất tôi từng sử dụng. Tôi tự hỏi nếu các shell khác hỗ trợ bất cứ điều gì tương tự (tức là khởi chạy ở chế độ nền mà không có tiếng ồn) - thật tuyệt vời nếu ai đó có thể đăng câu trả lời khác cho các shell khác.
Jeremy Visser

1
xem câu trả lời của tôi chỉ ra cách thực hiện với bất kỳ sh-lookalike nào
w00t

1
+1 vì có thể quyết định sau. Ngay lúc này tôi đã có nhu cầu này. làm việc như quảng cáo
code_monk

37

Công cụ nohup, có sẵn trên hầu hết các hộp Linux sẽ làm điều này.


1
Đây là câu trả lời đơn giản nhất. Mọi đầu ra từ đều được tự động chuyển đến nohup.out và có thể được kiểm tra sau.
Julian

3
nohup không yêu cầu zsh cả.
Aaron Brown

nohup là câu trả lời đúng, nó là viết tắt của không có hangup.
Kinjal Dixit

2
Nohup được tìm thấy trên nhiều máy hơn màn hình, vì vậy bạn nên biết cách sử dụng nó.
Zenon

27

Để được kỹ lưỡng, tôi sẽ chỉ ra tmux , có ý tưởng cơ bản giống như màn hình:

tmux được dự định là một sự thay thế hiện đại, được cấp phép BSD cho các chương trình như màn hình GNU. Các tính năng chính bao gồm:

  • Một giao diện lệnh mạnh mẽ, nhất quán, tài liệu tốt và dễ dàng có kịch bản.
  • Một cửa sổ có thể được chia theo chiều ngang và chiều dọc thành các tấm.
  • Các tấm có thể được tự do di chuyển và thay đổi kích thước, hoặc sắp xếp thành các bố trí đặt trước.
  • Hỗ trợ cho các thiết bị đầu cuối UTF-8 và 256 màu.
  • Sao chép và dán với nhiều bộ đệm.
  • Menu tương tác để chọn cửa sổ, phiên hoặc khách hàng.
  • Thay đổi cửa sổ hiện tại bằng cách tìm kiếm văn bản trong mục tiêu.
  • Khóa thiết bị đầu cuối, bằng tay hoặc sau khi hết thời gian.
  • Một codebase được cấp phép BSD sạch, dễ dàng mở rộng, đang được phát triển tích cực.

Tuy nhiên, việc tìm kiếm trên Google dễ dàng hơn nhiều.


2
Sử dụng "gnu screen"như truy vấn tìm kiếm của bạn hoạt động khá tốt.
gnur

4
+1000 cho tmux!
mbq

11

Màn hình quá mức cần thiết để chỉ giữ các quá trình chạy khi bạn đăng xuất.

Hãy thử dtach :

dtach là một chương trình được viết bằng C mô phỏng tính năng tách rời của màn hình, cho phép chương trình được thực thi trong môi trường được bảo vệ khỏi thiết bị đầu cuối điều khiển. Ví dụ, chương trình dưới sự kiểm soát của dtach sẽ không bị ảnh hưởng bởi thiết bị đầu cuối bị ngắt kết nối vì một số lý do.

dtach được viết vì màn hình không đáp ứng đầy đủ nhu cầu của tôi; Tôi không cần các tính năng bổ sung của màn hình, như hỗ trợ cho nhiều thiết bị đầu cuối hoặc hỗ trợ mô phỏng thiết bị đầu cuối. màn hình cũng quá to, cồng kềnh và có mã nguồn rất khó hiểu.

màn hình cũng cản trở việc tôi sử dụng các ứng dụng toàn màn hình như emacs và ircII, do sự giải thích quá mức của luồng giữa chương trình và các thiết bị đầu cuối kèm theo. dtach không có lớp mô phỏng đầu cuối và chuyển luồng đầu ra thô của chương trình tới các đầu cuối kèm theo. Quá trình xử lý đầu vào duy nhất mà dtach thực hiện là quét tìm ký tự tách (báo hiệu dtach tách ra khỏi chương trình) và xử lý khóa tạm dừng (thông báo cho dtach tạm thời ngừng hoạt động mà không ảnh hưởng đến chương trình đang chạy) và cả hai đều có thể bị vô hiệu hóa nếu muốn.

Trái ngược với màn hình, dtach có các tính năng tối thiểu và cực kỳ nhỏ. Điều này cho phép dtach dễ dàng kiểm tra các lỗi và lỗ hổng bảo mật hơn và làm cho nó có thể truy cập được trong các môi trường bị giới hạn không gian, chẳng hạn như trên các đĩa cứu hộ.


Cảm ơn bạn. Tôi đến đây chỉ để đăng về dtach quá. Bây giờ đây là điều tôi muốn làm cho thiết bị đầu cuối; màn hình làm CÁCH quá nhiều và cản trở đầu vào ở mức độ vô lý. Màn hình thực tế cần termcap riêng của nó là khá đáng lo ngại.
lông mịn

9

Đây là một cách để daemonize bất kỳ quá trình shell, không cần chương trình bên ngoài:

( while sleep 5; do date; done ) <&- >output.txt &

Sau đó, khi bạn đóng phiên của mình, công việc sẽ tiếp tục chạy như được chứng minh bằng tệp output.txt (có bộ đệm để mất một lúc để hiển thị khác không). Đừng quên giết công việc của bạn sau khi thử nghiệm.

Vì vậy, tất cả những gì bạn cần làm là đóng stdin và làm nền cho công việc. Để thực sự tốt, trước tiên, cd /vì vậy bạn không nên giữ một thú cưỡi.

Điều này hoạt động ngay cả trong sh đơn giản dưới Solaris.


Hấp dẫn. Điều đó nổi lên một số câu hỏi đáng chú ý. Tôi có thể thấy rằng bạn đặt STDIN thành không có gì, -toán tử? Sự khác biệt giữa < /dev/nullvà là &-gì? Tôi đoán rằng STDIN (và các STDIN và STDERR khác) có thể được chỉ định một tệp theo < filehoặc một luồng <& streamtrong trường hợp STDIN. Nó sẽ giống như sử dụng < /dev/nulltrong ví dụ của bạn ở trên? Và toán tử -ở trên có đề cập đến null là luồng không?
doc_id

Khi bạn thực hiện x <& -, sẽ đóng mô tả tệp x. Trong trường hợp này không có x, làm cho bash mặc định là 1, tức là đầu vào tiêu chuẩn. Nếu bạn sử dụng </ dev / null, bạn sẽ không đóng stdin, bạn chỉ cung cấp một tệp trống cho chương trình làm đầu vào.
w00t

1
Và thành thật mà nói tôi không thực sự biết lý do tại sao điều này thể hiện thứ bạn đang chạy :-) Mặc dù vậy, nó vẫn hoạt động, chúng tôi sử dụng nó trong sản xuất. Tôi phát hiện ra nó trong khi loay hoay với hy vọng tôi có thể tạo ra một quy trình trong vỏ mà không cần bất cứ điều gì đặc biệt - vì vậy tôi đã bắt đầu bằng cách đóng stdin và thế là đủ. Tôi nên đọc một số nguồn shell nhưng tôi cho rằng nếu bạn đóng stdin và làm nền cho quá trình, nó cũng làm mất quá trình.
w00t

2
Tôi nghĩ lý do là SIGHUP (tín hiệu thực tế khiến trẻ bỏ cuộc khi vỏ chết) được kích hoạt khi quá trình cha mẹ đóng tay cầm stdin của con. Tuy nhiên, nếu stdin bắt đầu là null, thay vì bị đóng sau thực tế, không có cách nào để cha mẹ kích hoạt SIGHUP. Mặc dù vậy, tìm thấy tốt đẹp - không bao giờ có thể nghĩ về điều đó.
Jeremy Visser

@JeremyVisser nghe có vẻ rất hợp lý!
w00t

7

Các atlệnh có thể hữu ích cho loại tình huống. Ví dụ: gõ:

at now

Và sau đó bạn có thể nhập một lệnh hoặc một loạt các lệnh sẽ được chạy. Kết quả sẽ được gửi qua email cho bạn, nếu e-mail được thiết lập chính xác trên máy.

Thay vì now, bạn có thể chỉ định thời gian tùy ý với ngày hoặc biểu thức thời gian như thế nào now + 15 minutes. Xem man atđể biết thêm chi tiết.


7

byobutrên Ubuntu là một giao diện đẹp cho màn hình. Bằng cách nhấn Ctrl- ?bạn có được một danh sách tất cả các phím tắt. Nó bổ sung một thanh trạng thái có thể hữu ích để xem tải CPU, dung lượng ổ đĩa, v.v. Nói chung, nó cung cấp trải nghiệm mà tôi sẽ mô tả như một kết nối VNC dựa trên thiết bị đầu cuối.

nohup cho phép bắt đầu một công việc trong nền với đầu ra của nó được định tuyến đến một tệp nhật ký, luôn có thể được chuyển hướng đến / dev / null nếu không cần thiết.

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.