मैं nohup के तहत पहले से चल रही प्रक्रिया को कैसे करूँ?


940

मेरे पास एक प्रक्रिया है जो पहले से ही लंबे समय से चल रही है और इसे समाप्त नहीं करना चाहती।

मैं इसे नोह के नीचे कैसे डाल सकता हूं (अर्थात, मैं इसे कैसे चालू रख सकता हूं, भले ही मैं टर्मिनल बंद कर दूं?)


29
समान समस्या का सामना करने वाले व्यक्ति को: याद रखें, कि भले ही आप टाइप करें yourExecutable &और आउटपुट स्क्रीन पर आते रहें और Ctrl+Cकुछ भी बंद न हो, बस आँख बंद करके टाइप करें disown;और Enterस्क्रीन को आउटपुट के साथ स्क्रॉल करने पर भी दबाएँ और आप यह नहीं देख सकते कि क्या आप टाइप कर रहे हैं। यह प्रक्रिया समाप्त हो जाएगी और आप बिना प्रक्रिया के मरने के बाद टर्मिनल को बंद कर पाएंगे।
नव

जवाबों:


1367

प्रक्रिया को पृष्ठभूमि में भेजने के लिए बैश के जॉब कंट्रोल का उपयोग करना :

  1. Ctrl+ Zकार्यक्रम को रोकने (रोकने) और वापस शेल में जाने के लिए।
  2. bg इसे पृष्ठभूमि में चलाने के लिए।
  3. disown -h [job-spec]जहां [job-spec] जॉब नंबर है (जैसे %1पहले चलने वाले जॉब के लिए; jobsकमांड के साथ अपने नंबर के बारे में पता करें ) ताकि टर्मिनल बंद होने पर जॉब न मारे।

38
जैसा कि यह सवाल था कि "इसे नोह के नीचे कैसे रखा जाए", disown -hशायद अधिक सटीक उत्तर है: "अवहेलना करें और अधिक व्यवहार करें जैसे नोह (यानी नौकरियां आपके वर्तमान शेल की प्रक्रिया के पेड़ में रहेंगी जब तक आप अपने शेल से बाहर नहीं निकल जाते हैं) यह आपको देखने की अनुमति देता है सभी नौकरियों कि यह खोल शुरू कर दिया। " ([ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… ) से
डॉ। जन-फिलिप गेहरके

8
मैं बाद में नौकरी कैसे वसूल करूं? मैं इसे ps -e का उपयोग करके चलाते हुए देख सकता हूं।
पाउलो कासारेटो

26
आप एक के बाद एक नौकरी के उत्पादन को नहीं देख सकते हैं disown, एक प्रक्रिया डिमॉन बनाती है, जिसका अर्थ है कि मानक इनपुट / आउटपुट को / dev / null पर पुनर्निर्देशित किया जाता है। इसलिए, यदि आप किसी नौकरी को my_job_command | tee my_job.log
खत्म

8
क्या किसी तरह 'my_job_command | आदेश चलने के बाद my_job.log को टी करें ?
एनरोड

23
disownप्रक्रिया से किसी भी पाइप को अलग करता है। पाइप को फिर से जोड़ने के लिए, इस धागेgdb में वर्णित अनुसार उपयोग करें । अधिक विशेष रूप से, यह पोस्ट
mbrownnyc

185

मान लीजिए किसी कारण से Ctrl+ Zभी काम नहीं कर रहा है, दूसरे टर्मिनल पर जाएं, प्रक्रिया आईडी ढूंढें (उपयोग करके ps) और चलाएं:

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOPप्रक्रिया को निलंबित करेगा और SIGCONTप्रक्रिया को पृष्ठभूमि में फिर से शुरू करेगा। तो अब, अपने दोनों टर्मिनलों को बंद करने से आपकी प्रक्रिया बंद नहीं होगी।


10
हाँ, एक OS समस्या है, विंडोज पर Cygwin के साथ काम नहीं करता है।
पुंग

6
यह भी बहुत उपयोगी है अगर नौकरी दूसरे ssh सत्र से शुरू की जाती है।
अमीर अली अकबरी 18

5
बस disown %1इसे बंद करने से पहले पहले टर्मिनल में करना याद रखें ।
फ्रेड

1
यह तब से उपयोगी है जब मैंने कंसोल के साथ एक ग्राफिकल इंटरफ़ेस शुरू किया (मेरे मामले में मैं kwinपरिणाम के बारे में सोचे बिना एक दुर्घटना के बाद कोनोला से शुरू हुआ)। इसलिए अगर मैं केविन को रोक देता, तो सब कुछ जम जाता और मुझे दौड़ने की कोई संभावना नहीं होती bg!
मिशेल

@ अगर मैंने ऐसा नहीं किया और ऐसा लगता रहा कि यह जारी रहेगा। संभव है या मैंने गलत पीआईडी ​​मारा?
कोई नहीं

91

रनिंग जॉब को शेल से अलग करने की कमांड (= इसे nohup बनाता है) disownऔर एक बेसिक शेल-कमांड है।

बैश-मैनपेज (मैन बैश) से:

disown [-ar] [-h] [jobspec ...]

विकल्पों के बिना, प्रत्येक कार्यक्षेत्र को सक्रिय नौकरियों की तालिका से हटा दिया जाता है। यदि -एच विकल्प दिया जाता है, तो प्रत्येक जॉबस्पेक को टेबल से नहीं हटाया जाता है, लेकिन इसे चिह्नित किया जाता है, ताकि शेल को राइट्स प्राप्त होने पर साइट पर काम न भेजा जाए। यदि कोई जॉबस्पेक मौजूद नहीं है, और न तो -a और -r विकल्प की आपूर्ति की जाती है, तो वर्तमान नौकरी का उपयोग किया जाता है। यदि कोई जॉबस्पेक की आपूर्ति नहीं की जाती है, तो सभी विकल्पों को हटाने या चिह्नित करने के लिए -a विकल्प का अर्थ है; नौकरी के तर्क के बिना -r विकल्प रनिंग जॉब के लिए ऑपरेशन को प्रतिबंधित करता है। रिटर्न वैल्यू 0 है जब तक कि जॉबस्पेक एक वैध नौकरी निर्दिष्ट नहीं करता है।

इसका मतलब है, कि एक सरल

disown -a

जॉब-टेबल से सभी नौकरियों को निकाल देगा और उन्हें नोहप बना देगा


9
disown -aसभी नौकरियों को निकालता है। एक साधारण disownकेवल वर्तमान नौकरी को हटा देता है। जैसा कि उत्तर में मैन पेज कहता है।
रुन शेजेलरूप फिलोसोफ

73

ये ऊपर अच्छे जवाब हैं, मैं सिर्फ एक स्पष्टीकरण जोड़ना चाहता था:

आप एक काम disownया प्रक्रिया नहीं कर सकते , आप disownएक नौकरी है, और यह एक महत्वपूर्ण अंतर है।

एक नौकरी एक ऐसी चीज है जो एक ऐसी प्रक्रिया की धारणा है जो एक शेल से जुड़ी हुई है, इसलिए आपको नौकरी को पृष्ठभूमि में फेंकना होगा (इसे निलंबित नहीं करना चाहिए) और फिर इसे भंग कर दिया।

मुद्दा:

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

यूनिक्स जॉब कंट्रोल की अधिक विस्तृत चर्चा के लिए http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ देखें ।


48

दुर्भाग्य disownसे सभी गोले में उपलब्ध नहीं है।

यूनिक्स के कुछ जायके (जैसे AIX और Solaris) के पास nohupकमांड पर ही एक विकल्प होता है जिसे एक रनिंग प्रोसेस पर लागू किया जा सकता है:

nohup -p pid

Http://en.wikipedia.org/wiki/Nohup देखें


केवल AIXऔर के लिए Solaris। "नोक के AIX और सोलारिस संस्करणों के पास एक -p विकल्प है जो भविष्य में होने वाले सिग्नल संकेतों को अनदेखा करने के लिए एक रनिंग प्रक्रिया को संशोधित करता है। बैश के उपर्युक्त वर्णित बिलिन के विपरीत, nohup -p प्रक्रिया आईडी को स्वीकार करता है।" स्रोत
बजे AlikElzin-kilaka

27

नोड का उत्तर वास्तव में बहुत अच्छा है, लेकिन इसने इस सवाल को खोल दिया कि कैसे स्टडआउट और स्टेडर पुनर्निर्देशित हो सकते हैं। मुझे यूनिक्स और लिनक्स पर एक समाधान मिला , लेकिन यह भी पूरा नहीं हुआ है। मैं इन दोनों समाधानों का विलय करना चाहूंगा। यह रहा:

अपने परीक्षण के लिए मैंने लूप.श नाम की एक छोटी सी बैश स्क्रिप्ट बनाई, जो एक अनंत लूप में एक मिनट की नींद के साथ अपने आप को प्रिंट करती है।

$./loop.sh

अब इस प्रक्रिया का पीआईडी ​​किसी तरह हासिल करें। आमतौर पर ps -C loop.shयह काफी अच्छा है, लेकिन यह मेरे मामले में छपा है।

अब हम दूसरे टर्मिनल पर जा सकते हैं (या ^ Z और उसी टर्मिनल में दबाएँ)। अब gdbइस प्रक्रिया से जुड़ा होना चाहिए।

$ gdb -p <PID>

यह स्क्रिप्ट को रोकता है (यदि चल रहा है)। इसकी स्थिति को चेक किया जा सकता है ps -f <PID>, जहां STATफ़ील्ड 'T +' है (या ^ Z 'T' के मामले में), जिसका अर्थ है (मैन 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

बंद (1) सफलता पर शून्य देता है।

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

ओपन (1) सफल होने पर नई फाइल डिस्क्रिप्टर लौटाता है।

यह खुला के साथ बराबर है open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)। के बजाय O_RDWR O_WRONLYलागू किया जा सकता है, लेकिन /usr/sbin/lsofसभी std * फ़ाइल हैंडलर ( FDकॉलम) के लिए 'u' कहते हैं , जो है O_RDWR

मैंने /usr/include/bits/fcntl.h हैडर फ़ाइल में मानों की जाँच की।

आउटपुट फ़ाइल के साथ खोला जा सकता है O_APPEND, जैसा nohupकि होगा, लेकिन यह man open(2)संभव NFS समस्याओं के कारण, द्वारा सुझाया नहीं गया है।

यदि हमें रिटर्न मान के रूप में -1 मिलता है, तो call perror("")त्रुटि संदेश प्रिंट करता है। अगर हमें ग़लती की ज़रूरत है, तो p errnogdb comand का उपयोग करें ।

अब हम नई पुनर्निर्देशित फ़ाइल की जांच कर सकते हैं। /usr/sbin/lsof -p <PID>प्रिंट:

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

अगर हम चाहते हैं, हम एक और फाइल करने के लिए stderr अनुप्रेषित अगर हम का उपयोग कर करना चाहते हैं कर सकते हैं call close(2)और call open(...)फिर एक अलग फ़ाइल नाम का उपयोग।

अब संलग्न bashको जारी करना होगा और हम छोड़ सकते हैं gdb:

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

यदि स्क्रिप्ट को gdbकिसी अन्य टर्मिनल से रोका गया था तो यह चलता रहता है। हम लूप.श टर्मिनल पर वापस जा सकते हैं। अब यह स्क्रीन के लिए कुछ भी नहीं लिखता है, लेकिन फ़ाइल में चल रहा है और लिख रहा है। हमें इसे पृष्ठभूमि में रखना होगा। तो दबाओ ^Z

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

(अब हम उसी स्थिति में हैं जैसे ^Zकि शुरुआत में दबाया गया था।)

अब हम नौकरी की स्थिति की जांच कर सकते हैं:

$ 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

इसलिए प्रक्रिया को पृष्ठभूमि में चलना चाहिए और टर्मिनल से अलग होना चाहिए। jobsवर्गाकार कोष्ठकों में कमांड के आउटपुट में संख्या अंदर की नौकरी की पहचान करती है bashbashजॉब नंबर से पहले '%' साइन अप करने वाले कमांड में निर्मित हम निम्न में उपयोग कर सकते हैं :

$ 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

और अब हम कॉलिंग बैश से बाहर निकल सकते हैं। प्रक्रिया पृष्ठभूमि में चलती रहती है। यदि हम इसकी PPID 1 (init (1) प्रक्रिया) बन जाते हैं और नियंत्रण टर्मिनल अज्ञात हो जाता है।

$ 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)

टिप्पणी

Gdb सामान को एक फाइल बनाते हुए स्वचालित किया जा सकता है (जैसे loop.gdb) जिसमें कमांड होते हैं और चलते हैं gdb -q -x loop.gdb -p <PID>। मेरा लूप। एसजीडी इस तरह दिखता है:

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

या इसके बजाय निम्नलिखित एक लाइनर का उपयोग कर सकते हैं:

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

मुझे उम्मीद है कि यह समाधान का एक पूर्ण विवरण है।


वास्तव में बहुत जानकारीपूर्ण, और सरल मामलों में अच्छी तरह से काम करने की संभावना है। लेकिन चेतावनी दी जाए, अधिक जटिल मामले बुरी तरह से विफल हो सकते हैं। मेरे पास आज उनमें से एक था: मेरी प्रक्रिया ने एक और प्रक्रिया को जन्म दिया था जिसने आउटपुट (संभवतः stderr के लिए) किया था, लेकिन अपने मास्टर के साथ संचार के लिए स्टडआउट हुक किया था। मास्टर्स एफडी को पुनर्निर्देशित करना प्रभावहीन था क्योंकि बच्चे को विरासत में स्टैडर मिला था, और चिल्ड स्टैडआउट को बंद करने से उस मास्टर को विफल कर दिया गया था जो पाइप के दूसरे छोर पर इंतजार कर रहा था। एक्स | बेटर्न अपनी प्रक्रियाओं को अच्छी तरह से जानते हैं इससे पहले कि आप यह कोशिश करें।
cmaster - मोनिका

@cmaster आप देख सकते हैं कि क्या एक हैंडल का उपयोग करके रीडायरेक्ट किया गया है lsof(फ़ाइल हैंडल का नाम ऐसा pipeनहीं है /dev/pts/1) या द्वारा ls -l /proc/<PID>/fd/<fd>(यह हैंडल के सिम्लिंक को दर्शाता है)। इसके अलावा सबप्रोसेस में अभी भी रीडायरेक्ट किए गए आउटपुट नहीं हो सकते हैं, जिन्हें किसी फाइल में रीडायरेक्ट किया जाना चाहिए।
ट्रू यूल

7

Nohup ( http://en.wikipedia.org/wiki/Nohup ) को रनिंग प्रक्रिया भेजने के लिए

nohup -p pid , यह मेरे लिए काम नहीं किया

फिर मैंने निम्नलिखित आदेशों को आजमाया और यह बहुत अच्छा काम किया

  1. कुछ SOMECOMMAND चलाएं, कहते हैं /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1

  2. Ctrl+ Zकार्यक्रम को रोकने (रोकने) और वापस शेल में जाने के लिए।

  3. bg इसे पृष्ठभूमि में चलाने के लिए।

  4. disown -h टर्मिनल बंद होने पर प्रक्रिया को नहीं मारा जाता है।

  5. exitशेल से बाहर निकलने के लिए टाइप करें क्योंकि अब आप जाने के लिए अच्छा है क्योंकि ऑपरेशन अपनी प्रक्रिया में पृष्ठभूमि में चलेगा, इसलिए यह शेल से बंधा नहीं है।

यह प्रक्रिया चलने के बराबर है nohup SOMECOMMAND


3

मेरे AIX सिस्टम पर, मैंने कोशिश की

nohup -p  processid>

इसने अच्छा काम किया। टर्मिनल विंडो बंद करने के बाद भी इसने मेरी प्रक्रिया को जारी रखा। हमारे पास डिफ़ॉल्ट शेल के रूप में ksh है इसलिए कमांड bgऔर disownकाम नहीं किया।


2
  1. ctrl+ z - इससे काम रुक जाएगा (रद्द नहीं होने वाला!)
  2. bg - यह काम को पृष्ठभूमि में रखेगा और चलने की प्रक्रिया में वापस लौटेगा
  3. disown -a - यह नौकरी के साथ सभी लगाव में कटौती करेगा (इसलिए आप टर्मिनल को बंद कर सकते हैं और यह अभी भी चलेगा)

ये सरल चरण आपको प्रक्रिया को चालू रखते हुए टर्मिनल को बंद करने की अनुमति देंगे।

यह nohupआपके प्रश्न की मेरी समझ के आधार पर नहीं लगाया जाएगा , आपको इसकी आवश्यकता नहीं है)।


मुझे लगता है कि डिस-ए के लिए व्यवहार सभी नौकरियों के साथ लगाव में कटौती करना है। हालांकि, यह स्टडिन / स्टडआउट पाइपलाइनों को बंद नहीं करता है, जिसका अर्थ है कि प्रक्रिया अभी भी टर्मिनल से लिखने (/ पढ़ने) की कोशिश करेगी
केल्टार

-2

इसने मेरे लिए Ubuntu लाइनक्स पर काम किया जबकि tcshell में।

  1. CtrlZ इसे रोकना है

  2. bg पृष्ठभूमि में चलाने के लिए

  3. jobs अपना जॉब नंबर पाने के लिए

  4. nohup %n जहां n नौकरी की संख्या है


2
नहीं, यह काम नहीं करता है:nohup: failed to run command '%1': No such file or directory
डनोटोटोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.