Bagaimana mencegah proses latar belakang dihentikan setelah menutup klien SSH di Linux

291

Saya sedang mengerjakan mesin Linux melalui SSH (Putty). Saya perlu membiarkan proses berjalan pada malam hari, jadi saya pikir saya bisa melakukan itu dengan memulai proses di latar belakang (dengan ampersand di akhir perintah) dan mengarahkan stdout ke file.

Yang mengejutkan saya, itu tidak berhasil. Segera setelah saya menutup jendela Putty, proses dihentikan.

Bagaimana saya bisa mencegah hal itu terjadi ??

Mendapatkan gratis
sumber

Jawaban:

301

Lihatlah program " nohup ".

JesperE
sumber
4
Bagaimana Anda menghentikannya setelah itu?
Derek Dahmer
9
Masuk dan lakukan "bunuh <pid>". Gunakan "pidof" jika Anda tidak tahu pid itu.
JesperE
32
Anda dapat menggunakan nohup command > /dev/null 2>&1 &untuk berjalan di latar belakang tanpa membuat stdout atau output stderr (tanpa nohup.outfile)
KCD
Bagaimana jika saya perlu memberikan beberapa masukan? Misalnya, saya memiliki skrip yang sudah berjalan lama yang harus saya jalankan di latar tetapi pertama-tama meminta kata sandi FTP saya. nohuptidak membantu dalam hal ini. Apakah ada cara untuk biola dengan Ctrl+Z/ bg?
Sergey
1
Karena saya malas dan buruk dalam menghafal urutan karakter yang samar, saya menulis ini , berdasarkan apa yang dikatakan @KCD, dan telah sering menggunakannya.
Anomali
167

Saya akan merekomendasikan menggunakan Layar GNU . Ini memungkinkan Anda untuk memutuskan sambungan dari server sementara semua proses Anda terus berjalan. Saya tidak tahu bagaimana saya hidup tanpanya sebelum saya tahu itu ada.

gpojd
sumber
7
Ini adalah salah satu perangkat lunak terhebat yang pernah saya gunakan. Serius. Saya menjalankannya pada kotak BSD yang saya sembunyikan dari mana saja, dan dapat dengan mudah melampirkan kembali ke layar saya dan memiliki semua terminal saya di mana saya melakukan segala macam hal.
Adam Jaskiewicz
1
Saya bisa membuktikan yang ini. Layar adalah aplikasi yang bagus. Kemampuan untuk melampirkan kembali luar biasa, dan menyimpan banyak pekerjaan yang berpotensi hilang.
willasaywhat
Saya bahkan menggunakannya di komputer lokal, dan melampirkan banyak xterms ke sesi layar yang sama (layar -x). Dengan begitu saya dapat membuka banyak jendela dalam sesi layar saya, dan dengan bebas mengalihkan berbagai xterms dari jendela ke jendela.
Adam Jaskiewicz
17
Tergantung pada apakah Anda perlu menyambung kembali ke aplikasi latar belakang atau tidak. Jika Anda melakukannya, ya, layar adalah satu-satunya cara untuk terbang. Namun, jika api-dan-lupa, maka nohup cocok dengan tagihan sama baiknya, jika tidak lebih baik.
Dave Sherohman
1
+1 untuk layar. Atau, sebagai alternatif, tmux (saya suka yang ini lebih dari layar) atau bahkan byobu, yang merupakan tampilan bagus untuk layar atau tmux. Anda bisa mengetik layar untuk mendapatkan shell untuk digunakan dan kembali nanti kapan saja, atau menjalankan perintah Anda dengan layar, seperti "perintah layar": sesi layar akan ada selama proses "perintah" ada, dan jika itu sesuatu sangat lama, Anda dapat kembali dan melihat output standarnya kapan saja.
gerlos
81

Ketika sesi ditutup, proses menerima sinyal SIGHUP yang tampaknya tidak ditangkap. Anda dapat menggunakan nohupperintah saat meluncurkan proses atau perintah bash built-in disown -hsetelah memulai proses untuk mencegah hal ini terjadi:

> 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.
Robert Gamble
sumber
4
Keuntungan di sini adalah bahwa penolakan bekerja untuk proses yang sudah dimulai.
Christian K.
1
Apakah 'jobspec' berarti pid?
Stewart
1
Jangan khawatir, temukan jawaban ini di sini stackoverflow.com/questions/625409/…
Stewart
42

dasmon? bukan? LAYAR? (tmux ftw, layar adalah sampah ;-)

Lakukan saja apa yang telah dilakukan setiap aplikasi lain sejak awal - garpu ganda.

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

Bang! Selesai :-) Saya sudah menggunakan ini berkali-kali pada semua jenis aplikasi dan banyak mesin lama. Anda dapat menggabungkan dengan arahan ulang dan yang lainnya untuk membuka saluran pribadi antara Anda dan proses.

Buat sebagai 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

lalu

# ./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

Dan begitulah, menelurkan apa pun. <(:) membuka pipa anonim melalui proses substitusi, yang mati, tetapi pipa tetap ada karena Anda memiliki pegangan untuk itu. Saya biasanya melakukan sleep 1alih - alih :karena itu sedikit bersemangat, dan saya akan mendapatkan kesalahan "file sibuk" - tidak pernah terjadi jika perintah nyata dijalankan (misalnya, command true)

"sumber heredoc":

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

Ini berfungsi pada setiap shell yang pernah saya coba, termasuk busybox / etc (initramfs). Saya belum pernah melihat itu dilakukan sebelumnya, saya secara mandiri menemukannya sambil mendorong, siapa tahu sumber bisa menerima argumen? Tetapi sering berfungsi sebagai bentuk eval yang jauh lebih mudah dikelola, jika ada hal seperti itu.

anthonyrisinger
sumber
2
mengapa suara turun ... jadi bagaimana jika pertanyaannya sudah lama; itu jelas relevan mengingat ada 11 jawaban lain yang payah. solusi ini adalah, sans systemd, cara idiomatis dan diterima untuk melakukan dasmon selama 30 tahun terakhir, bukan aplikasi yang tidak berguna, misalnya. nohup et al.
anthonyrisinger
7
tidak peduli seberapa bagus jawaban Anda, terkadang seseorang di SO tidak akan menyukainya dan akan downvote. Lebih baik tidak terlalu khawatir.
Alex D
1
@ tbc0 ... cobassh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger
1
@anthonyrisinger ok, itu berhasil. Saya pikir ini lebih bersih: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0
1
Ini bagus. satu-satunya solusi yang benar-benar berfungsi di busybox. pantas menerima lebih banyak suara
Hamy
34
nohup blah &

Ganti nama proses Anda dengan bla!

Brian Knoblauch
sumber
2
Anda mungkin ingin menambahkan standar pengalihan dan kesalahan standar.
David Nehme
9
nohup mengalihkan stdout dan stderr ke nohup.out (atau nohup.out dan nohup.err tergantung pada versinya), jadi kecuali jika Anda menjalankan banyak perintah, itu tidak perlu.
Chas. Owens
17

Secara pribadi, saya suka perintah 'batch'.

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

Ini memasukkannya ke latar belakang, dan kemudian mengirimkan hasilnya kepada Anda. Itu bagian dari cron.

Will Hartung
sumber
11

Seperti yang telah dicatat oleh orang lain, untuk menjalankan proses di latar belakang sehingga Anda dapat memutuskan sambungan dari sesi SSH Anda, Anda harus memiliki proses latar belakang memisahkan diri dengan benar dari terminal pengendali - yang merupakan pseudo-tty yang digunakan sesi SSH.

Anda dapat menemukan informasi tentang proses daemonisasi dalam buku-buku seperti Stevens "Advanced Network Program, Vol 1, 3rd Edn" atau Rochkind "Advanced Unix Programming".

Saya baru-baru ini (dalam beberapa tahun terakhir) harus berurusan dengan program bandel yang tidak daemonisasi sendiri dengan benar. Saya akhirnya berurusan dengan itu dengan membuat program daemonisasi generik - mirip dengan nohup tetapi dengan lebih banyak kontrol yang tersedia.

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)

Dash ganda adalah opsional pada sistem yang tidak menggunakan fungsi GNU getopt (); itu perlu (atau Anda harus menentukan POSIXLY_CORRECT di lingkungan) di Linux dll. Karena double-dash bekerja di mana-mana, yang terbaik adalah menggunakannya.

Anda masih dapat menghubungi saya (nama depan dot nama belakang di gmail dot com) jika Anda menginginkan sumbernya daemonize.

Namun, kode tersebut sekarang (akhirnya) tersedia di GitHub dalam repositori SOQ (Stack Overflow Questions) saya sebagai file daemonize-1.10.tgzdalam sub-direktori paket .

Jonathan Leffler
sumber
13
Mengapa Anda tidak meletakkan sumbernya di github atau bitbucket?
Rob
5
Mengapa tidak adanya sumber dari github menjamin downvote?
Jonathan Leffler
7
@JonathanLeffler IMHO mencantumkan semua opsi keren dari suatu program yang tidak tersedia untuk umum dalam bentuk apa pun (bahkan tidak secara komersial) berbatasan dengan membuang waktu pembaca.
DepressedDaniel
7

Pada sistem berbasis Debian (pada mesin jarak jauh) Instal:

sudo apt-get install tmux

Pemakaian:

tmux

jalankan perintah yang Anda inginkan

Untuk mengganti nama sesi:

Ctrl + B lalu $

atur Nama

Untuk keluar dari sesi:

Ctrl + B lalu D

(ini meninggalkan sesi tmux). Kemudian, Anda dapat keluar dari SSH.

Ketika Anda perlu kembali / memeriksanya lagi, mulai SSH, dan masukkan

tmux melampirkan session_name

Ini akan membawa Anda kembali ke sesi tmux Anda.

Maks
sumber
ini adalah cara untuk pergi
kilgoretrout
6

Untuk sebagian besar proses, Anda dapat pseudo-daemonize menggunakan trik baris perintah Linux lama ini:

# ((mycommand &)&)

Sebagai contoh:

# ((sleep 30 &)&)
# exit

Kemudian mulai jendela terminal baru dan:

# ps aux | grep sleep

Akan menunjukkan bahwa sleep 30masih berjalan.

Apa yang telah Anda lakukan adalah memulai proses sebagai anak dari seorang anak, dan ketika Anda keluar, nohupperintah yang biasanya akan memicu proses untuk keluar tidak mengalir turun ke cucu, meninggalkannya sebagai proses yatim piatu, masih berjalan .

Saya lebih suka ini "mengatur dan lupakan saja" pendekatan, tidak perlu berurusan dengan nohup, screen, tmux, I / o redirection, atau salah satu dari hal-hal itu.

RAM
sumber
5

Jika Anda menggunakan layar untuk menjalankan proses sebagai root, waspadalah terhadap kemungkinan serangan elevasi privilege. Jika akun Anda sendiri entah bagaimana dikompromikan, akan ada cara langsung untuk mengambil alih seluruh server.

Jika proses ini perlu dijalankan secara teratur dan Anda memiliki akses yang cukup di server, opsi yang lebih baik adalah menggunakan cron menjalankan pekerjaan. Anda juga bisa menggunakan init.d (super daemon) untuk memulai proses Anda di latar belakang, dan itu dapat berakhir segera setelah selesai.

Dana si Sane
sumber
5

nohupsangat bagus jika Anda ingin mencatat rincian Anda ke file. Tetapi ketika pergi ke latar belakang Anda tidak dapat memberikan kata sandi jika skrip Anda meminta. Saya pikir Anda harus mencoba screen. ini adalah utilitas yang dapat Anda instal pada distribusi linux Anda menggunakan yum misalnya pada CentOS yum install screenkemudian mengakses server Anda melalui dempul atau perangkat lunak lain, dalam jenis shell Anda screen. Ini akan membuka layar [0] di dempul. Lakukan pekerjaanmu. Anda dapat membuat lebih banyak layar [1], layar [2], dll dalam sesi dempul yang sama.

Perintah dasar yang perlu Anda ketahui:

Untuk memulai layar

layar


Untuk c layar berikutnya reate

ctrl + a + c


Untuk pindah ke layar n ext yang Anda buat

ctrl + a + n


Untuk d etach

ctrl + a + d


Selama bekerja tutup dempul Anda. Dan lain kali saat Anda masuk melalui tipe dempul

layar -r

Untuk menyambung kembali ke layar Anda, dan Anda dapat melihat proses Anda masih berjalan di layar. Dan untuk keluar dari layar ketik #exit.

Untuk lebih jelasnya lihat man screen.

Adeel Ahmad
sumber
dengan asumsi itu yumadalah alat yang tepat, ketika Anda tidak tahu distro, itu tidak baik. Anda harus memperjelas distro mana yang screendapat diinstal yum.
tymik
5

Nohup memungkinkan proses klien untuk tidak dibunuh jika proses induknya dimatikan, untuk argumen ketika Anda logout. Lebih baik lagi menggunakan:

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

Nohup membuat proses Anda mulai kebal terhadap pemutusan yang sesi SSH Anda dan proses anaknya terbunuh saat Anda logout. Perintah yang saya berikan memberi Anda cara Anda dapat menyimpan pid aplikasi dalam file pid sehingga Anda dapat membunuhnya dengan benar dan memungkinkan proses untuk berjalan setelah Anda logout.

jcodeninja
sumber
2

Jika Anda juga ingin menjalankan aplikasi X - gunakan xpra bersama "layar".

Alexey Shurygin
sumber
2

saya juga akan pergi untuk program layar (saya tahu bahwa jawaban orang lain adalah layar tetapi ini adalah penyelesaian)

tidak hanya fakta bahwa &, ctrl + z bg disown, nohup, dll. dapat memberi Anda kejutan buruk bahwa ketika Anda keluar dari pekerjaan, pekerjaan akan tetap terbunuh (saya tidak tahu mengapa, tapi itu terjadi pada saya, dan itu tidak mengganggu saya, dengan itu karena saya beralih menggunakan layar, tetapi saya kira solusi anthonyrisinger sebagai forking ganda akan menyelesaikannya), juga layar memiliki keuntungan besar hanya dengan back-grounding:

screen will background your process without losing interactive control to it

dan btw, ini adalah pertanyaan yang saya tidak akan pernah tanyakan di tempat pertama :) ... saya menggunakan layar dari awal saya melakukan apa pun di unix ... i (hampir) TIDAK PERNAH bekerja di shell unix / linux tanpa layar awal pertama ... dan saya harus berhenti sekarang, atau saya akan memulai presentasi tanpa akhir tentang apa layar yang baik dan apa yang bisa Anda lakukan untuk ya ... lihat sendiri, itu layak;)

Sang penyihir
sumber
PS anthonyrisinger, kamu baik-baik saja, kuberikan padamu ... 30 tahun? Saya yakin itu adalah solusi ketika &, bg, nohup atau layar belum ada, dan jangan tersinggung saya menghargai pengetahuan Anda tapi itu terlalu rumit untuk menggunakannya :)
PENULIS
2
(samping: lihat Tmux ) meskipun ini jauh sebelum saya [1987], &(eksekusi tidak serempak) diperkenalkan oleh shell Thompson pada tahun 1971 , untuk versi pertama UNIX ... jadi secara harfiah "selalu" ,-) sayangnya, Saya terlalu konservatif - sebenarnya sudah 41 tahun.
anthonyrisinger
2

Ada juga perintah daemon dari paket libslack open-source.

daemon cukup dapat dikonfigurasi dan peduli tentang semua hal daemon yang membosankan seperti restart otomatis, logging atau penanganan pidfile.

janv
sumber
2

Tambahkan string ini ke perintah Anda:> & - 2> & - <& - &. > & - Berarti tutup stdout. 2> & - berarti close stderr. <& - berarti stdin dekat. & Berarti berjalan di latar belakang. Ini berfungsi untuk memulai pekerjaan secara terprogram melalui ssh, juga:

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

Jawaban yang diterima menyarankan menggunakan nohup . Saya lebih suka menyarankan menggunakan PM2 . Menggunakan pm2 lebih dari nohup memiliki banyak keuntungan, seperti menjaga aplikasi tetap hidup, memelihara file log untuk aplikasi dan banyak lagi fitur lainnya. Untuk lebih detail lihat ini .

Untuk menginstal pm2 Anda harus mengunduh npm . Untuk sistem berbasis Debian

sudo apt-get install npm

dan untuk Redhat

sudo yum install npm

Atau Anda dapat mengikuti instruksi ini . Setelah menginstal npm, gunakan untuk menginstal pm2

npm install pm2@latest -g

Setelah selesai, Anda dapat memulai aplikasi dengan

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

Untuk pemantauan proses gunakan perintah berikut:

$ 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

Kelola proses menggunakan nama aplikasi atau id proses atau kelola semua proses secara bersamaan:

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

File log dapat ditemukan di

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

File biner yang dapat dieksekusi juga dapat dijalankan menggunakan pm2. Anda harus membuat perubahan ke file jason. Ubah "exec_interpreter" : "node", untuk "exec_interpreter" : "none".(lihat bagian atribut ).

#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;
}

Kompilasi kode di atas

gcc -o hello hello.c  

dan jalankan dengan np2 di latar belakang

pm2 start ./hello
haccks
sumber
Bisakah ini digunakan untuk menjalankan executable biner?
GetFree
@Mendapatkan gratis; Iya. Kamu bisa.
haccks
Tolong tambahkan contoh. Jawabannya seperti sekarang sepertinya hanya baik untuk file skrip.
GetFree
@Mendapatkan gratis; Menambahkan contoh. Beri tahu saya jika Anda memiliki masalah.
pukul
1

Di systemd / Linux, systemd-run adalah alat yang bagus untuk meluncurkan proses sesi-independen. Pembenci akan selalu membenci

Eugene Shatsky
sumber