Halihazırda çalışan bir işlemi nohup altına nasıl koyabilirim?


940

Zaten uzun süredir devam eden bir süreç var ve bitirmek istemiyorum.

Nohup altına nasıl koyabilirim (yani, terminali kapatsam bile çalışmaya devam etmesini nasıl sağlayabilirim?)


29
Aynı sorunla karşılaşan herkese: Unutmayın, yourExecutable &yazıp çıktılar ekranda gelmeye devam ediyor ve Ctrl+Chiçbir şey durmuyor gibi görünse de , ekran çıktılarla kaydırılsa bile körü körüne yazın disown;ve basın Enterve yazıyorsun. İşlem reddedilecek ve işlem ölmeden terminali kapatabileceksiniz.
Nav

Yanıtlar:


1367

İşlemi arka plana göndermek için bash'ın İş Denetimini kullanma :

  1. Ctrl+ Zprogramı durdurmak (duraklatmak) ve kabuğa geri dönmek için.
  2. bg arka planda çalıştırmak için.
  3. disown -h [job-spec]burada [job-spec] iş numarasıdır ( %1ilk çalışan işte olduğu gibi; jobskomutla numaranızı bulun ), böylece terminal kapatıldığında iş öldürülmez.

38
Soru "nasıl nohup altına koymak" disown -holduğu için , belki de daha kesin bir cevaptır: "reddetme daha çok nohup gibi davranır (yani kabuktan çıkana kadar işler mevcut kabuğunuzun işlem ağacında kalacaktır) Bu görmenizi sağlar bu merminin başladığı tüm işler. " ([ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… adresinden )
-Philip Gehrcke

8
İşi daha sonra nasıl kurtarırım? Ben ps-e kullanarak çalışan görebilirsiniz.
Paulo Casaretto

26
A disown, disown bir işlemi bir artalan programı haline getirdikten sonra bir işin çıktısını göremezsiniz, yani standart girdi / çıktı / dev / null'a yönlendirilir. Bu nedenle, bir işi reddetmeyi planlıyorsanız, bir dosyaya giriş my_job_command | tee my_job.log
yapmakla

8
nasıl bir şekilde 'my_job_command | tee my_job.log ' komut zaten çalıştıktan sonra ?
arod

23
disownboruları işlemden ayırır. Boruları yeniden takmak için bu ipliktegdb açıklandığı gibi kullanın . Daha spesifik olarak, bu yazı .
mbrownnyc

185

Herhangi bir nedenle Ctrl+ ' Znın da çalışmadığını varsayalım , başka bir terminale git, işlem kimliğini bul (kullan ps) ve çalıştır:

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOPişlemi askıya alır ve SIGCONTarka planda işleme devam eder. Şimdi, her iki terminalinizi de kapatmak işleminizi durdurmayacak.


10
Evet, bu bir işletim sistemi sorunu, kill Windows'ta Cygwin ile çalışmıyor.
Pungs

6
Ayrıca iş başka bir ssh oturumundan başlatılırsa çok yararlıdır.
Amir Ali Akbari

5
disown %1Kapatmadan önce ilk terminalde yapmayı unutmayın .
fred

1
Konsol ile grafiksel bir arayüz başlattığım için yararlıdır (benim durumumda, kwinbir çarpışmadan sonra sonuçları düşünmeden konsole başladım ). Yani eğer kwin'i durdursaydım, her şey donmuş olacaktı ve koşma imkanım yoktu bg!
Michele

@fred Bunu yapmadım ve koşmaya devam ediyor gibiydi. Mümkün mü yoksa yanlış PID'ye mi vurdum?
Kimse

91

Çalışan bir işi kabuktan ayırma komutu (= bunu nohup yapar) disownve temel bir kabuk komutudur.

Bash-manpage'den (man bash):

reddetme [-ar] [-h] [jobspec ...]

Seçenekler olmadan, her jobpec aktif işler tablosundan kaldırılır. -H seçeneği belirtilirse, her jobpec öğesi tablodan kaldırılmaz, ancak kabuk SIGHUP alırsa SIGHUP işe gönderilmeyecek şekilde işaretlenir. Hiç jobpec yoksa ve ne -a ne de -r seçeneği sağlanmazsa, geçerli iş kullanılır. Hiç jobpec sağlanmazsa, -a seçeneği tüm işleri kaldırmak veya işaretlemek anlamına gelir; jobspec bağımsız değişkeni olmadan -r seçeneği, işlemi çalışan işler ile sınırlar. Jobspec geçerli bir iş belirtmedikçe, dönüş değeri 0'dır.

Bu, basit bir

disown -a

tüm işleri iş tablosundan kaldıracak ve onları nohup yapacak


9
disown -atüm işleri kaldırır. Basit bir işlem disownyalnızca geçerli işi kaldırır. Cevaptaki man sayfasının söylediği gibi.
Rune Schjellerup Philosof

73

Bunlar yukarıdaki iyi cevaplar, sadece bir açıklama eklemek istedim:

disownBir pid veya işlem yapamazsınız, bir işsiniz disownve bu önemli bir ayrımdır.

Bir iş, bir kabuğa bağlı bir süreç kavramı olan bir şeydir, bu nedenle işi arka plana atmanız (askıya almamanız) ve daha sonra reddetmeniz gerekir.

Konu:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1

Unix İş Denetiminin daha ayrıntılı bir tartışması için http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ adresine bakın .


48

Ne yazık ki disownbash'a özgüdür ve tüm kabuklarda mevcut değildir.

Unix'in bazı tatları (örn. AIX ve Solaris), nohupkomutun kendisinde çalışan bir işleme uygulanabilecek bir seçeneğe sahiptir:

nohup -p pid

Bkz. Http://en.wikipedia.org/wiki/Nohup


Sadece AIXve için Solaris. Msgstr "Nohup'un AIX ve Solaris sürümlerinde, çalışmakta olan bir işlemi gelecekteki SIGHUP sinyallerini yok saymak için değiştiren bir -p seçeneği vardır. Kaynak
AlikElzin-kilaka

27

Düğümün cevabı gerçekten harika, ama stdout ve stderr'in nasıl yeniden yönlendirilebileceği sorusunu açık bıraktı. Unix ve Linux'ta bir çözüm buldum , ancak tamamlanmadı. Bu iki çözümü birleştirmek istiyorum. İşte burada:

Testim için loop.sh adlı küçük bir bash betiği yaptım, bu da pid'i sonsuz bir döngüde bir dakika uyku ile bastı.

$./loop.sh

Şimdi bu işlemin PID'sini bir şekilde alın. Genellikle ps -C loop.shyeterince iyidir, ancak benim durumumda yazdırılır.

Şimdi başka bir terminale geçebiliriz (veya ^ Z ve aynı terminalde tuşuna basabiliriz). Şimdi gdbbu sürece eklenmelidir.

$ gdb -p <PID>

Bu komut dosyasını durdurur (çalışıyorsa). Durumu ps -f <PID>, STATalanın 'T +' olduğu (veya ^ Z 'T' olması durumunda) ile kontrol edilebilir, yani (adam ps (1))

    T Stopped, either by a job control signal or because it is being traced
    + is in the foreground process group

(gdb) call close(1)
$1 = 0

Kapat (1) başarı durumunda sıfır döndürür.

(gdb) call open("loop.out", 01102, 0600)
$6 = 1

Open (1), başarılı olursa yeni dosya tanımlayıcısını döndürür.

Bu açık eşittir open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Bunun yerine O_RDWR O_WRONLYuygulanabilir, ancak /usr/sbin/lsoftüm std * dosya işleyicileri ( FDsütun) için 'u' diyor , yani O_RDWR.

/Usr/include/bits/fcntl.h başlık dosyasındaki değerleri kontrol ettim.

Çıktı dosyası ile açılabilir O_APPENDgibi nohupyapacağını, ancak bu önerdiği edilmez man open(2)çünkü olası NFS problemleri.

Dönüş değeri olarak -1 alırsak call perror(""), hata iletisini yazdırır. Errno'ya ihtiyacımız olursa, p errnogdb comand kullanın .

Şimdi yeni yönlendirilen dosyayı kontrol edebiliriz. /usr/sbin/lsof -p <PID>baskılar:

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out

İstersek, stderr'ı başka bir dosyaya yeniden yönlendirebiliriz, eğer başka bir dosya adı kullanarak call close(2)ve call open(...)tekrar kullanırsak.

Şimdi ekteki bashserbest bırakılmalıdır ve bırakabiliriz gdb:

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q

Komut dosyası gdbbaşka bir terminalden durdurulmuşsa çalışmaya devam eder. Loop.sh'nin terminaline geri dönebiliriz. Şimdi ekrana hiçbir şey yazmıyor, dosyaya çalışıyor ve yazıyor. Bunu arka plana koymalıyız. Yani basın ^Z.

^Z
[1]+  Stopped                 ./loop.sh

(Şimdi ^Zbaşlangıçta basıldığımız durumdayız .)

Şimdi işin durumunu kontrol edebiliriz:

$ ps -f 24522
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh
$ jobs
[1]+  Stopped                 ./loop.sh

Bu yüzden süreç arka planda çalışmalı ve terminalden ayrılmalıdır. jobsKomutun çıktısındaki köşeli parantez içindeki sayı, içindeki işi tanımlar bash. bashİş numarasından önce '%' işareti uygulayarak aşağıdaki yerleşik komutlarda kullanabiliriz :

$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh

Ve şimdi çağıran bash'tan çıkabiliriz. İşlem arka planda çalışmaya devam eder. PPID'den ayrılırsak 1 (init (1) işlemi) olur ve kontrol terminali bilinmez olur.

$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID>     1  0 11:16 ?        S      0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey    0u   CHR 136,36                38 /dev/pts/36 (deleted)
loop.sh <PID> truey    1u   REG   0,26     1127 15008411 /home/truey/loop.out
loop.sh <PID> truey    2u   CHR 136,36                38 /dev/pts/36 (deleted)

YORUM YAP

Gdb öğeleri otomatik olarak komutları içeren bir dosya (ör. Loop.gdb) oluşturabilir ve çalıştırılabilir gdb -q -x loop.gdb -p <PID>. Benim loop.gdb şöyle görünür:

call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit

Ya da bunun yerine aşağıdaki bir astar kullanılabilir:

gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>

Umarım bu çözümün oldukça eksiksiz bir tanımıdır.


Gerçekten çok bilgilendirici ve basit durumlarda iyi çalışması muhtemeldir. Ancak, daha karmaşık vakaların sefil bir şekilde başarısız olabileceği konusunda uyarılmalıdır. Bugün bunlardan biri vardı: Sürecim, çıktıyı (muhtemelen stderr'a) yapan başka bir süreci ortaya çıkardı, ancak ustasıyla iletişim için stdout bağladı. Master FD'leri yeniden yönlendirmek etkisizdi çünkü çocuk stderr'ı miras almıştı ve childs stdout'unun kapatılması borunun diğer ucunda bekleyen efendide başarısız oldu. X- | Bettern bunu denemeden önce süreçlerinizi iyi biliyor.
cmaster - eski haline monica

@cmaster Bir tanıtıcıyı kullanarak lsof(dosya tanıtıcısının adı pipegibi değil /dev/pts/1) veya tarafından ls -l /proc/<PID>/fd/<fd>(bu tanıtıcı sembolik bağlantısını gösterir ) yönlendirilip yönlendirilmediğini denetleyebilirsiniz . Ayrıca, alt süreçler yine de bir dosyaya yeniden yönlendirilmesi gereken çıkışları yeniden yönlendiremez.
TrueY

7

Çalışan işlemi nohup'a göndermek için ( http://en.wikipedia.org/wiki/Nohup )

nohup -p pid , benim için çalışmadı

Sonra aşağıdaki komutları denedim ve çok iyi çalıştı

  1. Biraz SOMECOMMAND yönetin /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.

  2. Ctrl+ Zprogramı durdurmak (duraklatmak) ve kabuğa geri dönmek için.

  3. bg arka planda çalıştırmak için.

  4. disown -h böylece terminal kapandığında süreç öldürülmez.

  5. Kabuktan exitçıkmak için yazın çünkü artık işlem kendi işleminde arka planda çalışacağı için gitmeye hazırsınız, bu yüzden bir kabuğa bağlı değil.

Bu işlem koşmaya eşdeğerdir nohup SOMECOMMAND.


3

AIX sistemimde denedim

nohup -p  processid>

Bu iyi çalıştı. Terminal pencerelerini kapattıktan sonra bile işlemimi sürdürmeye devam etti. Varsayılan kabuk olarak ksh'ımız var, bu nedenle bgve disownkomutları çalışmadı.


2
  1. ctrl+ z - bu işi duraklatır (iptal edilmez!)
  2. bg - Bu işin arkaplanını ve çalışma sürecine geri dönmesini sağlar
  3. disown -a - bu, tüm eki iş ile keser (böylece terminali kapatabilirsiniz ve yine de çalışır)

Bu basit adımlar, işlemi devam ettirirken terminali kapatmanıza olanak tanır.

Yapmayacak nohup(sorunuz hakkındaki anlayışım temelinde, burada buna ihtiyacınız yok).


Bence reddedilme davranışı -a tüm işlere bağlılığı azaltmaktır. Bununla birlikte, stdin / stdout boru hatlarını kapatmaz, bu da işlemin terminalden yazmaya (/ okumaya) devam edeceği anlamına gelir
Kelthar

-2

Bu benim için tcshell iken Ubuntu linux üzerinde çalıştı.

  1. CtrlZ duraklatmak için

  2. bg arka planda çalıştırmak

  3. jobs iş numarasını almak için

  4. nohup %n burada n iş numarasıdır


2
Hayır, çalışmıyor:nohup: failed to run command '%1': No such file or directory
Dunatotatos
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.