Cách ngăn quá trình nền bị dừng sau khi đóng máy khách SSH trong Linux


291

Tôi đang làm việc trên máy Linux thông qua SSH (Putty). Tôi cần phải để lại một quá trình chạy trong đêm, vì vậy tôi nghĩ rằng tôi có thể làm điều đó bằng cách bắt đầu quá trình ở chế độ nền (với dấu và ở cuối lệnh) và chuyển hướng stdout sang tệp.

Thật ngạc nhiên, điều đó không làm việc. Ngay khi tôi đóng cửa sổ Putty, quá trình dừng lại.

Làm thế nào tôi có thể ngăn chặn điều đó xảy ra ??

Câu trả lời:


301

Kiểm tra chương trình " nohup ".


4
Làm thế nào để bạn dừng nó sau đó?
Derek Dahmer

9
Đăng nhập và thực hiện "kill <pid>". Sử dụng "pidof" nếu bạn không biết pid.
JesperE

32
Bạn có thể sử dụng nohup command > /dev/null 2>&1 &để chạy trong nền mà không cần tạo bất kỳ đầu ra tiêu chuẩn hoặc thiết bị xuất chuẩn nào (không có nohup.outtệp)
KCD

Nếu tôi cần cung cấp một số đầu vào thì sao? Ví dụ: tôi có một tập lệnh chạy dài mà tôi cần chạy trong nền nhưng trước tiên nó yêu cầu mật khẩu FTP của tôi. nohupkhông giúp đỡ trong trường hợp này. Có cách nào để mân mê với Ctrl+Z/ bg?
Serge

1
Vì tôi lười biếng và tệ trong việc ghi nhớ các chuỗi ký tự khó hiểu, tôi đã viết , dựa trên những gì @KCD nói, và đã sử dụng nó rất nhiều.
Bất thường

167

Tôi khuyên bạn nên sử dụng GNU Screen . Nó cho phép bạn ngắt kết nối với máy chủ trong khi tất cả các quy trình của bạn tiếp tục chạy. Tôi không biết làm thế nào tôi sống mà không có nó trước khi tôi biết nó tồn tại.


7
Đây là một trong những phần mềm tuyệt vời nhất tôi từng sử dụng. Nghiêm túc. Tôi có nó chạy trên hộp BSD mà tôi đã nhập từ MỌI NƠI, và có thể chỉ cần gắn lại vào màn hình của tôi và có tất cả các thiết bị đầu cuối của tôi, nơi tôi đang làm đủ thứ.
Adam Jaskiewicz

1
Tôi có thể chứng thực điều này. Màn hình là một ứng dụng tuyệt vời. Khả năng gắn lại là tuyệt vời, và tiết kiệm rất nhiều công việc có khả năng bị mất.
willasaywhat

Tôi thậm chí sử dụng nó trên các máy cục bộ và đính kèm nhiều xterms vào cùng một phiên màn hình (screen -x). Bằng cách đó, tôi có thể mở nhiều cửa sổ trong phiên màn hình của mình và tự do chuyển đổi các xterms khác nhau của mình từ cửa sổ này sang cửa sổ khác.
Adam Jaskiewicz

17
Phụ thuộc vào việc bạn có cần kết nối lại với ứng dụng chạy nền hay không. Nếu bạn làm, thì, vâng, màn hình là cách duy nhất để bay. Tuy nhiên, nếu đó là lửa và quên, thì nohup phù hợp với hóa đơn cũng như vậy, nếu không tốt hơn.
Dave Sherohman

1
+1 cho màn hình. Hoặc, như là một thay thế, tmux (tôi thích cái này hơn màn hình) hoặc thậm chí là byobu, đó là một lối vào đẹp cho màn hình hoặc tmux. Bạn chỉ có thể gõ màn hình để lấy shell để sử dụng và quay lại bất cứ lúc nào hoặc chạy lệnh bằng màn hình, như "lệnh màn hình": phiên màn hình sẽ tồn tại miễn là quá trình "lệnh" tồn tại và nếu đó là một cái gì đó rất lâu, bạn có thể quay lại và xem đầu ra tiêu chuẩn của nó bất cứ lúc nào.
gerlos

81

Khi phiên được đóng, quá trình sẽ nhận được tín hiệu SIGHUP mà nó dường như không bắt được. Bạn có thể sử dụng nohuplệnh khi khởi chạy tiến trình hoặc lệnh bash tích hợp disown -hsau khi bắt đầu quá trình để ngăn điều này xảy ra:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.

4
Ưu điểm ở đây là không thích làm việc cho các quy trình đã được bắt đầu.
Christian K.

1
'Jobspec' có nghĩa là pid?
Stewart

1
Đừng lo lắng, đã tìm thấy câu trả lời này tại đây stackoverflow.com/questions/625409/ từ
Stewart

42

daemonize? không sao MÀN? (tmux ftw, màn hình là rác ;-)

Chỉ cần làm những gì mọi ứng dụng khác đã làm kể từ đầu - double fork.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

Bang! Xong :-) Tôi đã sử dụng vô số lần này trên tất cả các loại ứng dụng và nhiều máy cũ. Bạn có thể kết hợp với chuyển hướng và không có gì để mở một kênh riêng giữa bạn và quá trình.

Tạo dưới dạng coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

và sau đó

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

Và ở đó bạn đi, sinh sản bất cứ điều gì. <(:) mở một đường ống ẩn danh thông qua quá trình thay thế quá trình, nó chết, nhưng đường ống dính xung quanh vì bạn có tay cầm với nó. Tôi thường làm sleep 1thay :vì vì nó hơi kém và tôi gặp lỗi "tập tin bận" - không bao giờ xảy ra nếu một lệnh thực sự được chạy (ví dụ command true:)

"Tìm nguồn cung ứng":

. /dev/stdin <<EOF
[...]
EOF

Điều này hoạt động trên mọi shell duy nhất tôi từng thử, bao gồm busybox / etc (initramfs). Tôi chưa bao giờ thấy nó được thực hiện trước đây, tôi độc lập phát hiện ra nó trong khi prodding, ai biết nguồn có thể chấp nhận args? Nhưng nó thường phục vụ như một hình thức eval dễ quản lý hơn nhiều, nếu có một điều như vậy.


2
tại sao bỏ phiếu xuống ... vậy nếu câu hỏi đã cũ; rõ ràng có liên quan khi xem xét có 11 câu trả lời khác. giải pháp này là, sans systemd, cách thức thành ngữ và được chấp nhận để tạo ra trong 30 năm qua, không phải là các ứng dụng vô nghĩa, ví dụ. nohup et al.
anthonyrisinger

7
cho dù câu trả lời của bạn tốt đến đâu, đôi khi ai đó trên SO sẽ không thích nó và sẽ hạ bệ. Tốt hơn hết là đừng lo lắng về nó quá nhiều.
Alex D

1
@ tbc0 ... hãy thửssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger

1
@anthonyrisinger ok, cái đó hiệu quả. Tôi nghĩ cái này sạch hơn: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0

1
Điều đó thật tuyệt. giải pháp duy nhất thực sự hoạt động trong busybox. nó xứng đáng nhận được nhiều sự ủng hộ hơn
Hamy

34
nohup blah &

Thay thế tên quy trình của bạn cho blah!


2
bạn có thể muốn thêm tiêu chuẩn chuyển hướng ra và lỗi tiêu chuẩn.
David Nehme

9
nohup chuyển hướng stdout và stderr sang nohup.out (hoặc nohup.out và nohup.err tùy thuộc vào phiên bản), vì vậy trừ khi bạn đang chạy nhiều lệnh thì không cần thiết.
Chas. Owens

17

Cá nhân, tôi thích lệnh 'lô'.

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

Điều này sẽ đưa nó vào nền, và sau đó gửi kết quả cho bạn. Đó là một phần của cron.


11

Như những người khác đã lưu ý, để chạy một quy trình trong nền để bạn có thể ngắt kết nối khỏi phiên SSH của mình, bạn cần có quy trình nền tách rời chính nó khỏi thiết bị đầu cuối kiểm soát của nó - đó là giả mà phiên SSH sử dụng.

Bạn có thể tìm thấy thông tin về các quy trình tạo daemon trong các cuốn sách như "Chương trình mạng nâng cao, Tập 1, Edn 3" của Stevens hoặc "Lập trình Unix nâng cao" của Rochkind.

Gần đây tôi (trong vài năm gần đây) đã phải đối phó với một chương trình tính toán lại mà không tự điều chỉnh đúng cách. Tôi đã kết thúc việc xử lý bằng cách tạo ra một chương trình trình bày chung chung - tương tự như nohup nhưng có sẵn nhiều điều khiển hơn.

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

Dấu gạch ngang kép là tùy chọn trên các hệ thống không sử dụng hàm GNU getopt (); nó là cần thiết (hoặc bạn phải chỉ định POSIXLY_CORRECT trong môi trường) trên Linux, v.v. Vì dash-dash hoạt động ở mọi nơi, tốt nhất nên sử dụng nó.

Bạn vẫn có thể liên hệ với tôi (tên đầu tiên dấu chấm cuối cùng tại gmail dot com) nếu bạn muốn nguồn cho daemonize.

Tuy nhiên, mã hiện có (cuối cùng) có sẵn trên GitHub trong kho lưu trữ SOQ (Câu hỏi tràn bộ) của tôi dưới dạng tệp daemonize-1.10.tgztrong thư mục con gói .


13
Tại sao bạn không đặt nguồn trên github hoặc bitbucket?
Cướp

5
Tại sao sự vắng mặt của nguồn từ github đảm bảo một downvote?
Jonathan Leffler

7
@JonathanLeffler IMHO liệt kê tất cả các tùy chọn thú vị của một chương trình không có sẵn công khai dưới bất kỳ hình thức nào (thậm chí không thương mại) giáp với việc lãng phí thời gian của người đọc.
DepressionDaniel

7

Trên hệ thống dựa trên Debian (trên máy từ xa) Cài đặt:

sudo apt-get cài đặt tmux

Sử dụng:

tmux

chạy các lệnh bạn muốn

Để đổi tên phiên:

Ctrl + B rồi $

đặt tên

Để thoát phiên:

Ctrl + B rồi D

(điều này rời khỏi phiên tmux). Sau đó, bạn có thể đăng xuất khỏi SSH.

Khi bạn cần quay lại / kiểm tra lại, hãy khởi động SSH và nhập

tmux đính kèm session_name

Nó sẽ đưa bạn trở lại phiên tmux của bạn.


đây là con đường để đi
kilgoretrout

6

Đối với hầu hết các quy trình, bạn có thể giả daemon bằng cách sử dụng thủ thuật dòng lệnh Linux cũ này:

# ((mycommand &)&)

Ví dụ:

# ((sleep 30 &)&)
# exit

Sau đó bắt đầu một cửa sổ terminal mới và:

# ps aux | grep sleep

Sẽ cho thấy rằng sleep 30vẫn đang chạy.

Những gì bạn đã làm là bắt đầu quá trình khi còn là một đứa trẻ và khi bạn thoát ra, nohuplệnh thông thường sẽ kích hoạt quy trình để thoát không đổ xuống cho đứa cháu, để nó như một quá trình mồ côi, vẫn chạy .

Tôi thích này "đặt nó và quên nó" cách tiếp cận, không cần phải đối phó với nohup, screen, tmux, I / o chuyển hướng, hay bất cứ thứ đó.


5

Nếu bạn sử dụng màn hình để chạy một tiến trình với quyền root, hãy cẩn thận với khả năng các cuộc tấn công nâng cao đặc quyền. Nếu tài khoản của bạn bị xâm phạm bằng cách nào đó, sẽ có một cách trực tiếp để chiếm toàn bộ máy chủ.

Nếu quá trình này cần được chạy thường xuyên và bạn có đủ quyền truy cập trên máy chủ, một lựa chọn tốt hơn sẽ là sử dụng cron khi chạy công việc. Bạn cũng có thể sử dụng init.d (siêu daemon) để bắt đầu quá trình của bạn trong nền và nó có thể chấm dứt ngay khi hoàn thành.


5

nohuplà rất tốt nếu bạn muốn đăng nhập thông tin của bạn vào một tập tin. Nhưng khi nó vào nền, bạn không thể cung cấp cho nó mật khẩu nếu tập lệnh của bạn yêu cầu. Tôi nghĩ bạn phải cố gắng screen. đó là một tiện ích bạn có thể cài đặt trên bản phân phối linux của mình bằng cách sử dụng yum, ví dụ như trên CentOS, yum install screensau đó truy cập máy chủ của bạn thông qua putty hoặc phần mềm khác, trong loại vỏ của bạn screen. Nó sẽ mở màn hình [0] trong putty. Làm công việc của bạn. Bạn có thể tạo thêm màn hình [1], màn hình [2], v.v. trong cùng một phiên putty.

Các lệnh cơ bản bạn cần biết:

Để bắt đầu màn hình

màn


Để c reate màn hình tiếp theo

ctrl + a + c


Để di chuyển đến n màn hình mở rộng bạn đã tạo

ctrl + a + n


Đến d etach

ctrl + a + d


Trong khi làm việc đóng putty của bạn. Và lần sau khi bạn đăng nhập thông qua loại putty

màn hình -r

Để kết nối lại với màn hình của bạn và bạn có thể thấy quy trình của mình vẫn đang chạy trên màn hình. Và để thoát khỏi kiểu màn hình #exit.

Để biết thêm chi tiết xem man screen.


giả sử đó yumlà công cụ phù hợp, khi bạn không biết bản phân phối, thì không tốt. bạn nên làm rõ những distro nào screencó thể được cài đặt yum.
tymik

5

Nohup cho phép một tiến trình khách hàng không bị giết nếu tiến trình cha bị giết, đối số khi bạn đăng xuất. Thậm chí tốt hơn vẫn sử dụng:

nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohup làm cho quá trình bạn bắt đầu miễn dịch với việc chấm dứt mà phiên SSH và quy trình con của nó bị giết khi bạn đăng xuất. Lệnh tôi đã cung cấp cho bạn một cách bạn có thể lưu trữ pid của ứng dụng trong tệp pid để bạn có thể giết nó một cách chính xác sau đó và cho phép quá trình chạy sau khi bạn đã đăng xuất.




2

Tôi cũng sẽ đi cho chương trình màn hình (tôi biết rằng một số câu trả lời khác là màn hình nhưng đây là một sự hoàn thành)

không chỉ thực tế là &, ctrl + z bg bị từ chối, nohup, v.v. có thể mang đến cho bạn một bất ngờ khó chịu rằng khi bạn đăng xuất công việc vẫn sẽ bị giết (tôi không biết tại sao, nhưng nó đã xảy ra với tôi, và nó không làm phiền với lý do là tôi đã chuyển sang sử dụng màn hình, nhưng tôi đoán giải pháp anthonyrisinger là việc gấp đôi sẽ giải quyết điều đó), màn hình cũng có một lợi thế lớn so với chỉ nền tảng:

screen will background your process without losing interactive control to it

và btw, đây là câu hỏi tôi sẽ không bao giờ hỏi ở nơi đầu tiên :) ... tôi sử dụng màn hình từ khi bắt đầu làm bất cứ điều gì trong bất kỳ unix nào ... tôi (gần như) KHÔNG BAO GIỜ làm việc trong trình bao unix / linux mà không bắt đầu màn hình đầu tiên ... và tôi nên dừng ngay bây giờ, hoặc tôi sẽ bắt đầu một bài thuyết trình bất tận về màn hình tốt là gì và những gì có thể làm cho bạn ... hãy tự mình tìm kiếm nó, nó đáng giá;)


PS anthonyrisinger, bạn tốt, tôi cho bạn điều đó nhưng ... 30 năm? Tôi cá rằng đó là một giải pháp khi &, bg, nohup hoặc màn hình chưa có, và không có ý xúc phạm tôi đánh giá cao kiến ​​thức của bạn nhưng điều đó quá phức tạp để sử dụng nó :)
THESorcerer

2
(sang một bên: xem Tmux ) mặc dù điều này có trước rất nhiều đối với tôi [1987], &(thực thi không đồng bộ) đã được giới thiệu bởi lớp vỏ Thompson vào năm 1971 , cho phiên bản đầu tiên của UNIX ... vì vậy nó có nghĩa đen là "luôn luôn" ; Tôi đã quá bảo thủ - thực sự đã 41 năm.
anthonyrisinger

2

Ngoài ra còn có lệnh daemon của gói libslack mã nguồn mở.

daemon là khá cấu hình và không quan tâm đến tất cả các công cụ daemon tẻ nhạt như tự động khởi động lại, đăng nhập hoặc xử lý pidfile.


2

Nối chuỗi này vào lệnh của bạn:> & - 2> & - <& - &. > & - có nghĩa là thiết bị xuất chuẩn gần. 2> & - có nghĩa là stderr gần. <& - có nghĩa là stdin gần gũi. & có nghĩa là chạy trong nền. Điều này cũng hoạt động để bắt đầu một công việc thông qua ssh:

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$


1

Chấp nhận câu trả lời đề nghị sử dụng nohup . Tôi muốn đề nghị sử dụng pm2 . Sử dụng pm2 so với nohup có nhiều lợi thế, như giữ cho ứng dụng tồn tại, duy trì các tệp nhật ký cho ứng dụng và nhiều tính năng khác. Để biết thêm chi tiết kiểm tra này .

Để cài đặt pm2 bạn cần tải xuống npm . Dành cho hệ thống dựa trên Debian

sudo apt-get install npm

và cho Redhat

sudo yum install npm

Hoặc bạn có thể làm theo các hướng dẫn này . Sau khi cài đặt npm, hãy sử dụng nó để cài đặt pm2

npm install pm2@latest -g

Sau khi hoàn thành, bạn có thể bắt đầu ứng dụng của mình bằng cách

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

Để giám sát quá trình sử dụng các lệnh sau:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

Quản lý các quy trình bằng tên ứng dụng hoặc id tiến trình hoặc quản lý tất cả các quy trình cùng nhau:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

Các tệp nhật ký có thể được tìm thấy trong

$HOME/.pm2/logs #contain all applications logs

Các tệp thực thi nhị phân cũng có thể được chạy bằng pm2. Bạn phải thay đổi tập tin jason. Thay đổi "exec_interpreter" : "node", thành "exec_interpreter" : "none".(xem phần thuộc tính ).

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

Biên dịch mã trên

gcc -o hello hello.c  

và chạy nó với np2 trong nền

pm2 start ./hello

Điều này có thể được sử dụng để chạy thực thi nhị phân?
GetFree

@Dùng miễn phí; Đúng. Bạn có thể.
haccks

Xin vui lòng thêm một ví dụ. Câu trả lời là ngay bây giờ có vẻ như nó chỉ tốt cho các tệp script.
GetFree

@Dùng miễn phí; Đã thêm ví dụ. Hãy cho tôi biết nếu bạn có bất kỳ vấn đề.
haccks

1

Trên systemd / Linux, systemd-run là một công cụ tuyệt vời để khởi chạy các quy trình độc lập với phiên. Ghét sẽ ghé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.