Linux'ta SSH istemcisini kapattıktan sonra arka plan işleminin durdurulması nasıl önlenir


291

SSH (Putty) aracılığıyla bir Linux makinesinde çalışıyorum. Bir işlemi gece boyunca çalışır durumda bırakmam gerekiyor, bu yüzden işlemi arka planda (komutun sonunda bir ve işareti ile) başlatarak ve stdout'u bir dosyaya yönlendirerek yapabileceğimi düşündüm.

Benim için sürpriz değil. Macun penceresini kapatır kapatmaz süreç durur.

Bunun olmasını nasıl önleyebilirim?

Yanıtlar:


301

" Nohup " programını inceleyin.


4
Daha sonra nasıl durdurursunuz?
Derek Dahmer

9
Giriş yapın ve "kill <pid>" yapın. Eğer pid bilmiyorsanız "pidof" kullanın.
JesperE

32
nohup command > /dev/null 2>&1 &Herhangi bir stdout veya stderr çıktısı oluşturmadan arka planda çalıştırmak için kullanabilirsiniz ( nohup.outdosya yok )
KCD

Biraz girdi sağlamam gerekirse ne olur? Örneğin, arka planda çalıştırmam gereken uzun süren bir komut dosyası var, ancak önce FTP şifremi istiyor. nohupbu durumda yardımcı olmaz. Ctrl+Z/ İle uğraşmanın bir yolu var mı bg?
Sergey

1
Ben karakterlerin şifreli dizileri ezberlemek de tembel ve kötü olduğum için, yazdığım bu @KCD söylediklerini dayalı ve onu çok kullanıyoruz.
Anomali

167

GNU Screen kullanmanızı tavsiye ederim . Tüm işlemleriniz çalışmaya devam ederken sunucunun bağlantısını kesmenize olanak tanır. Var olduğunu bilmeden onsuz nasıl yaşadığımı bilmiyorum.


7
Bu şimdiye kadar kullandığım en büyük yazılım parçalarından biri. Ciddi anlamda. Ben HER YERDEN içine ssh bir BSD kutusu üzerinde çalışan var, ve sadece benim ekran yeniden takın ve her türlü şeyler yaptığım tüm terminallerim var.
Adam Jaskiewicz

1
Bunu kanıtlayabilirim. Ekran harika bir uygulamadır. Yeniden takma yeteneği şaşırtıcıdır ve potansiyel olarak kayıp işlerden tasarruf sağlar.
willasaywhat

Hatta yerel makinelerde kullanıyorum ve aynı ekran oturumuna birden çok xterms ekliyorum (ekran -x). Bu şekilde ekran oturumumda birçok pencere açabilir ve çeşitli xtermlerimi pencereden pencereye serbestçe değiştirebilirim.
Adam Jaskiewicz

17
Arka plandaki uygulamaya yeniden bağlanmanız gerekip gerekmediğine bağlıdır. Eğer yaparsanız, evet, ekran uçmanın tek yoludur. Yine de, eğer ateşle ve unutsa, nohup daha iyi olmasa bile faturaya güzelce uyar.
Dave Sherohman

1
Ekran için +1. Alternatif olarak, ekran veya tmux için güzel bir ön uç olan tmux (bunu ekrandan daha çok seviyorum) veya hatta byobu. İstediğiniz zaman kullanmak ve daha sonra dönmek için bir kabuk almak için ekran yazabilir veya komutunuzu ekranla çalıştırabilirsiniz, örneğin "ekran komutu": ekran oturumu "komut" işlemi var olduğu sürece ve bir şey varsa çok uzun, geri dönebilir ve standart çıktısına istediğiniz zaman bakabilirsiniz.
gerlos

81

Oturum kapatıldığında, süreç anlaşılan yakalamadığı SIGHUP sinyalini alır. Sen kullanabilirsiniz nohupsüreci veya yerleşik komuta bash başlatırken komutu disown -hBunu engellemek için işlemi başladıktan sonra:

> 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
Buradaki avantaj, daha önce başlatılmış olan süreçler için reddetme çalışmalarının yapılmasıdır.
Christian K.

1
'Jobspec' pid anlamına mı geliyor?
Stewart

1
Endişeye gerek yok, bu cevabı burada buldum stackoverflow.com/questions/625409/…
Stewart

42

Artalanda? nohup? EKRAN? (tmux ftw, ekran önemsiz ;-)

Çift çatal - Sadece her uygulamanın başından beri ne yaptığını yapın.

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

Bang! Bitti :-) Bu sayısız kez her türlü uygulamada ve birçok eski makinede kullandım. Siz ve işlem arasında özel bir kanal açmak için yeniden yönlendirmelerle ya da ne ile birleştirebilirsiniz.

Coproc.sh olarak oluşturun:

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

ve sonra

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

Ve işte gidiyorsun, ne olursa olsun doğ. <(:), işlem değişikliği ile anonim bir boru açar, bu da ölür, ancak boru bir sapınız olduğu için etrafta yapışır. Genellikle biraz açık saçıklık sleep 1yerine bunun yerine yaparım :ve "dosya meşgul" hatası alırdım - gerçek bir komut çalıştırılırsa asla olmaz (örn. command true)

"yorumlu kaynak":

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

Bu, busybox / etc (initramfs) dahil olmak üzere şimdiye kadar denediğim her kabuk üzerinde çalışır. Daha önce hiç yapıldığını görmedim, prodding yaparken bağımsız olarak keşfettim, kaynağın argümanları kabul edebileceğini kim bilebilirdi? Ancak böyle bir şey varsa, genellikle çok daha yönetilebilir bir değerlendirme biçimi olarak hizmet eder.


2
neden aşağı oy ... peki ya soru eski ise; emici başka 11 cevap olduğu göz önüne alındığında açıktır. Bu çözümler, sans systemd, anlamsız uygulamalar değil, son 30 yıl için arka plan oluşturmanın deyimsel ve kabul edilen yoludur. nohup ve ark.
anthonyrisinger

7
Cevabınız ne kadar iyi olursa olsun, bazen SO'daki biri hoşuna gitmeyecek ve aşağı düşecektir. Çok fazla endişelenmemek daha iyi.
Alex D

1
@ tbc0 ... deneyinssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger

1
@anthonyrisinger tamam, işe yarıyor. Bunun daha temiz olduğunu düşünüyorum: ssh myhost 'sleep 500 >&- 2>&- <&- &'
TMTOWTDI

1
Bu harika. gerçekten meşgul kutusunda çalışan tek çözüm. o daha fazla upvotes hak ediyor
Hamy

34
nohup blah &

İşlem adınızı yerine koyun!


2
yönlendirme standart çıkışı ve standart hata eklemek isteyebilirsiniz.
David Nehme

9
nohup stdout ve stderr'i nohup.out'a (veya sürüme bağlı olarak nohup.out ve nohup.err) yönlendirir, bu nedenle birden fazla komut çalıştırmadığınız sürece gerekli değildir.
Chas. Owens

17

Şahsen, 'toplu iş' komutunu seviyorum.

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

Bu, arka plana doldurur ve ardından sonuçları size gönderir. Bu cron'un bir parçası.


11

Diğerlerinin de belirttiği gibi, arka planda bir işlemi çalıştırmak için SSH oturumunuzdan bağlantıyı kesebilmeniz için, arka plan işleminin kendisini kontrol terminalinden (SSH oturumunun kullandığı takma ad olan) doğru bir şekilde ayırması gerekir.

Programlama süreçleriyle ilgili bilgileri Stevens'ın "Advanced Network Program, Cilt 1, 3rd Edn" veya Rochkind'in "Advanced Unix Programming" gibi kitaplarında bulabilirsiniz.

Son zamanlarda (son birkaç yıl içinde) kendisini düzgün bir şekilde arka plana almayan bir yeniden kirletici programla uğraşmak zorunda kaldım. Bununla, nohup'a benzer, ancak daha fazla kontrol mevcut olan genel bir arka plan programı oluşturarak başa çıktım.

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)

Çift tire, GNU getopt () işlevini kullanmayan sistemlerde isteğe bağlıdır; Linux'ta gereklidir (ya da çevrede POSIXLY_CORRECT belirtmeniz gerekir) vb. Çift çizgi her yerde çalıştığından, kullanmak en iyisidir.

Kaynağını istiyorsanız yine de benimle iletişime geçebilirsiniz (gmail dot com'da ad soyadı adı) daemonize.

Ancak, kod artık (son olarak) GitHub'da SOQ (Yığın Taşması Soruları) veri havuzumda paketler alt dizinindeki dosya daemonize-1.10.tgzolarak kullanılabilir .


13
Neden kaynağı github veya bitbucket'e koymuyorsunuz?
Rob

5
Kaynağın github'dan yokluğu neden bir aşağı oy gerektiriyor?
Jonathan Leffler

7
@JonathanLeffler IMHO okur zamanını boşa harcanan herhangi bir biçimde (ticari olarak bile değil) halka açık olmayan bir programın tüm serin seçenekleri listeler.
DepressedDaniel

7

Debian tabanlı bir sistemde (uzak makinede) Kurulum:

sudo uygun-get install tmux

Kullanımı:

tmux

istediğiniz komutları çalıştırın

Oturumu yeniden adlandırmak için:

Ctrl + B sonra $

adı ayarla

Oturumdan çıkmak için:

Ctrl + B sonra D

(bu tmux oturumundan ayrılır). Ardından SSH oturumunu kapatabilirsiniz.

Geri dönmeniz / tekrar kontrol etmeniz gerektiğinde, SSH'yi başlatın ve

tmux oturum_adı ekle

Sizi tmux oturumunuza geri götürecektir.


Bu gitmek için yol
kilgoretrout

6

Çoğu işlem için bu eski Linux komut satırı hilesini kullanarak sözde daemonize edebilirsiniz:

# ((mycommand &)&)

Örneğin:

# ((sleep 30 &)&)
# exit

Ardından yeni bir terminal penceresi başlatın ve:

# ps aux | grep sleep

sleep 30Hala çalıştığını gösterecek .

Yaptığınız şey, bir çocuğun çocuğu olarak süreci başlatmaktır ve çıktığınızda, nohupnormalde çıkmak için işlemi tetikleyecek olan komut, büyük çocuğa doğru kademelendirilmez ve yetim bir süreç olarak kalır ve hala çalışır .

Bu "ayarla ve unut" yaklaşımı ile başa çıkmak için gerek tercih nohup, screenI / O yönlendirmesi, tmux, ya da herhangi bir madde.


5

Bir işlemi kök olarak çalıştırmak için ekranı kullanırsanız, ayrıcalık yükselme saldırılarına dikkat edin. Kendi hesabınız bir şekilde ele geçirilirse, sunucunun tamamını ele geçirmenin doğrudan bir yolu olacaktır.

Bu işlemin düzenli olarak yapılması gerekiyorsa ve sunucuda yeterli erişiminiz varsa, işi çalıştırmak için cron'u kullanmak daha iyi bir seçenek olacaktır. Ayrıca, işleminizi arka planda başlatmak için init.d (süper daemon) kullanabilirsiniz ve işlem yapılır yapılmaz sona erebilir.


5

nohupayrıntılarınızı bir dosyaya kaydetmek istiyorsanız çok iyi. Ancak arka plana gittiğinde, komut dosyalarınız isterse şifre veremezsiniz. Bence denemelisin screen. Örneğin CentOS'ta yum kullanarak linux dağıtımınıza yükleyebileceğiniz bir yardımcı programdır ve yum install screendaha sonra sunucunuza macun veya kabuk türünüzdeki başka bir yazılım aracılığıyla erişebilirsiniz screen. Ekranı [0] macunla açar. İşini yap. Aynı macun seansında daha fazla ekran [1], ekran [2] vb. Oluşturabilirsiniz.

Bilmeniz gereken temel komutlar:

Ekranı başlatmak için

ekran


To c REATE sonraki ekranda

CTRL + a + c


Oluşturduğunuz n dahili ekrana geçmek için

CTRL + a + n


To d etach

CTRL + a + d


Çalışma sırasında macununuzu kapatın. Ve bir dahaki sefere macun türü ile giriş yaptığınızda

ekran -r

Ekranınıza yeniden bağlanmak için işleminizin hala ekranda çalıştığını görebilirsiniz. Ekrandan çıkmak için #exit yazın.

Daha fazla bilgi için bkz man screen.


yumdağıtımın ne olduğunu bilmediğinizde, bunun doğru araç olduğunu varsaymak iyi değildir. hangi dağıtımların screenyüklenebileceğini açıkça belirtmelisiniz yum.
timik

5

Nohup, bir üst süreç öldürülürse, bir istemci işleminin, oturumu kapattığınızda argüman olarak öldürülmesine izin vermez. Daha da iyisi hala kullanmak:

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

Nohup, SSH oturumunuzun ve alt süreçlerinizin oturumunuzu kapattıktan sonra öldürdüğü sonlandırmaya karşı bağışık olmaya başladığınız işlemi yapar. Verdiğim komut, uygulamanın pid'ini bir pid dosyasında saklayabilmeniz için bir yol sağlar, böylece daha sonra doğru bir şekilde öldürebilir ve oturumu kapattıktan sonra işlemin çalışmasına izin verir.




2

Ayrıca ekran programı için gitmek istiyorum (some1 else cevap ekran olduğunu biliyorum ama bu bir tamamlanma)

sadece, & ctrl + z bg disown, nohup, vb. gerçeği, oturumunuzu kapattığınızda hala öldürüleceğine dair kötü bir sürpriz verebilir (neden bilmiyorum, ama bana oldu ve rahatsız etmedi) bununla birlikte ekranı kullanmaya neden olmalıyım, ancak çift çatallama bunu çözeceği için anthonyrisinger çözümünü tahmin ediyorum), ayrıca ekranın sadece arka topraklamaya göre büyük bir avantajı var :

screen will background your process without losing interactive control to it

ve btw, bu ilk etapta asla sormayacağım bir soru :) ... ben herhangi bir unix bir şey yapmanın başından ekran kullanın ... i (neredeyse) ASLA başlangıç ​​ekranı olmadan bir unix / linux kabuk çalışmak Önce ... ve şimdi durmalıyım, yoksa iyi bir ekranın ne olduğunu ve sizin için neler yapabileceğinin sonsuz bir sunumunu başlatacağım ... kendiniz arayın, buna değer;)


PS anthonyrisinger, iyisin, sana veriyorum ama ... 30 yıl? Bahse girerim, &, bg, nohup veya ekran henüz orada değildi ve hiçbir suç i bilginizi takdir ama kullanmak için çok karmaşık :)
THESorcerer 30:12

2
(bir yana: Tmux'a bakın ) bu beni büyük ölçüde öncelemesine rağmen [1987], &(eşzamansız yürütme) Thompson kabuğu tarafından 1971'de UNIX'in ilk sürümü için tanıtıldı ... bu yüzden kelimenin tam anlamıyla "her zaman" olmuştur ;-) alas, Çok muhafazakartım - aslında 41 yıl oldu.
anthonyrisinger

2

Açık kaynak libslack paketinin daemon komutu da var .

daemon oldukça yapılandırılabilir ve otomatik yeniden başlatma, günlüğe kaydetme veya pidfile işleme gibi tüm sıkıcı daemon şeylerini önemsiyor.


2

Bu dizeyi komutunuza ekleyin:> & - 2> & - <& - &. > & - yakın stdout anlamına gelir. 2> & - yakın stderr anlamına gelir. <& - yakın stdin anlamına gelir. & arka planda çalıştırmak anlamına gelir. Bu, bir işi ssh aracılığıyla da programlı olarak başlatmak için çalışır:

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


1

Kabul edilen cevap nohup kullanılmasını önerir . Ben pm2 kullanmanızı öneririz . Kullanılması PM2 üzerinde nohup günlük uygulama için dosya ve çok daha başka özellikler korumak, uygulama hayatta tutmak gibi birçok avantajı vardır. Daha fazla ayrıntı için buna göz atın .

Yüklemek için um2'den indirmek gerekir NPM . Debian tabanlı sistem için

sudo apt-get install npm

ve Redhat için

sudo yum install npm

Veya bu talimatları takip edebilirsiniz . Kurduktan sonra npm yüklemek için kullanacağım bunu PM2

npm install pm2@latest -g

Tamamlandığında, uygulamanızı şu şekilde başlatabilirsiniz:

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

Süreç izleme için aşağıdaki komutları kullanın:

$ 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

Uygulama adını veya işlem kimliğini kullanarak işlemleri yönetin veya tüm işlemleri birlikte yönetin:

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

Günlük dosyaları şurada bulunabilir:

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

İkili yürütülebilir dosyalar pm2 kullanılarak da çalıştırılabilir. Jason dosyasında bir değişiklik yapmanız gerekir. Değişim "exec_interpreter" : "node"için, "exec_interpreter" : "none".(bkz öznitelikler bölümüne ).

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

Kodun üstünde derleme

gcc -o hello hello.c  

ve arka planda np2 ile çalıştır

pm2 start ./hello

Bu ikili yürütülebilir dosyaları çalıştırmak için kullanılabilir mi?
GetFree

@Bedava al; Evet. Yapabilirsin.
haccks

Lütfen bir örnek ekleyin. Şu anda olduğu gibi cevap sadece komut dosyaları için iyi görünüyor.
GetFree

@Bedava al; Örnek eklendi. Herhangi bir sorunuz varsa bana bildirin.
haccks

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.