मेरे पास एक प्रक्रिया है जो पहले से ही लंबे समय से चल रही है और इसे समाप्त नहीं करना चाहती।
मैं इसे नोह के नीचे कैसे डाल सकता हूं (अर्थात, मैं इसे कैसे चालू रख सकता हूं, भले ही मैं टर्मिनल बंद कर दूं?)
मेरे पास एक प्रक्रिया है जो पहले से ही लंबे समय से चल रही है और इसे समाप्त नहीं करना चाहती।
मैं इसे नोह के नीचे कैसे डाल सकता हूं (अर्थात, मैं इसे कैसे चालू रख सकता हूं, भले ही मैं टर्मिनल बंद कर दूं?)
जवाबों:
प्रक्रिया को पृष्ठभूमि में भेजने के लिए बैश के जॉब कंट्रोल का उपयोग करना :
bg
इसे पृष्ठभूमि में चलाने के लिए।disown -h [job-spec]
जहां [job-spec] जॉब नंबर है (जैसे %1
पहले चलने वाले जॉब के लिए; jobs
कमांड के साथ अपने नंबर के बारे में पता करें ) ताकि टर्मिनल बंद होने पर जॉब न मारे।disown -h
शायद अधिक सटीक उत्तर है: "अवहेलना करें और अधिक व्यवहार करें जैसे नोह (यानी नौकरियां आपके वर्तमान शेल की प्रक्रिया के पेड़ में रहेंगी जब तक आप अपने शेल से बाहर नहीं निकल जाते हैं) यह आपको देखने की अनुमति देता है सभी नौकरियों कि यह खोल शुरू कर दिया। " ([ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… ) से
disown
, एक प्रक्रिया डिमॉन बनाती है, जिसका अर्थ है कि मानक इनपुट / आउटपुट को / dev / null पर पुनर्निर्देशित किया जाता है। इसलिए, यदि आप किसी नौकरी को my_job_command | tee my_job.log
मान लीजिए किसी कारण से Ctrl+ Zभी काम नहीं कर रहा है, दूसरे टर्मिनल पर जाएं, प्रक्रिया आईडी ढूंढें (उपयोग करके ps
) और चलाएं:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
प्रक्रिया को निलंबित करेगा और SIGCONT
प्रक्रिया को पृष्ठभूमि में फिर से शुरू करेगा। तो अब, अपने दोनों टर्मिनलों को बंद करने से आपकी प्रक्रिया बंद नहीं होगी।
disown %1
इसे बंद करने से पहले पहले टर्मिनल में करना याद रखें ।
kwin
परिणाम के बारे में सोचे बिना एक दुर्घटना के बाद कोनोला से शुरू हुआ)। इसलिए अगर मैं केविन को रोक देता, तो सब कुछ जम जाता और मुझे दौड़ने की कोई संभावना नहीं होती bg
!
रनिंग जॉब को शेल से अलग करने की कमांड (= इसे nohup बनाता है) disown
और एक बेसिक शेल-कमांड है।
बैश-मैनपेज (मैन बैश) से:
disown [-ar] [-h] [jobspec ...]
विकल्पों के बिना, प्रत्येक कार्यक्षेत्र को सक्रिय नौकरियों की तालिका से हटा दिया जाता है। यदि -एच विकल्प दिया जाता है, तो प्रत्येक जॉबस्पेक को टेबल से नहीं हटाया जाता है, लेकिन इसे चिह्नित किया जाता है, ताकि शेल को राइट्स प्राप्त होने पर साइट पर काम न भेजा जाए। यदि कोई जॉबस्पेक मौजूद नहीं है, और न तो -a और -r विकल्प की आपूर्ति की जाती है, तो वर्तमान नौकरी का उपयोग किया जाता है। यदि कोई जॉबस्पेक की आपूर्ति नहीं की जाती है, तो सभी विकल्पों को हटाने या चिह्नित करने के लिए -a विकल्प का अर्थ है; नौकरी के तर्क के बिना -r विकल्प रनिंग जॉब के लिए ऑपरेशन को प्रतिबंधित करता है। रिटर्न वैल्यू 0 है जब तक कि जॉबस्पेक एक वैध नौकरी निर्दिष्ट नहीं करता है।
इसका मतलब है, कि एक सरल
disown -a
जॉब-टेबल से सभी नौकरियों को निकाल देगा और उन्हें नोहप बना देगा
disown -a
सभी नौकरियों को निकालता है। एक साधारण disown
केवल वर्तमान नौकरी को हटा देता है। जैसा कि उत्तर में मैन पेज कहता है।
ये ऊपर अच्छे जवाब हैं, मैं सिर्फ एक स्पष्टीकरण जोड़ना चाहता था:
आप एक काम disown
या प्रक्रिया नहीं कर सकते , आप disown
एक नौकरी है, और यह एक महत्वपूर्ण अंतर है।
एक नौकरी एक ऐसी चीज है जो एक ऐसी प्रक्रिया की धारणा है जो एक शेल से जुड़ी हुई है, इसलिए आपको नौकरी को पृष्ठभूमि में फेंकना होगा (इसे निलंबित नहीं करना चाहिए) और फिर इसे भंग कर दिया।
मुद्दा:
% jobs
[1] running java
[2] suspended vi
% disown %1
यूनिक्स जॉब कंट्रोल की अधिक विस्तृत चर्चा के लिए http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ देखें ।
दुर्भाग्य disown
से सभी गोले में उपलब्ध नहीं है।
यूनिक्स के कुछ जायके (जैसे AIX और Solaris) के पास nohup
कमांड पर ही एक विकल्प होता है जिसे एक रनिंग प्रोसेस पर लागू किया जा सकता है:
nohup -p pid
AIX
और के लिए Solaris
। "नोक के AIX और सोलारिस संस्करणों के पास एक -p विकल्प है जो भविष्य में होने वाले सिग्नल संकेतों को अनदेखा करने के लिए एक रनिंग प्रक्रिया को संशोधित करता है। बैश के उपर्युक्त वर्णित बिलिन के विपरीत, nohup -p प्रक्रिया आईडी को स्वीकार करता है।" स्रोत
नोड का उत्तर वास्तव में बहुत अच्छा है, लेकिन इसने इस सवाल को खोल दिया कि कैसे स्टडआउट और स्टेडर पुनर्निर्देशित हो सकते हैं। मुझे यूनिक्स और लिनक्स पर एक समाधान मिला , लेकिन यह भी पूरा नहीं हुआ है। मैं इन दोनों समाधानों का विलय करना चाहूंगा। यह रहा:
अपने परीक्षण के लिए मैंने लूप.श नाम की एक छोटी सी बैश स्क्रिप्ट बनाई, जो एक अनंत लूप में एक मिनट की नींद के साथ अपने आप को प्रिंट करती है।
$./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 errno
gdb 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
वर्गाकार कोष्ठकों में कमांड के आउटपुट में संख्या अंदर की नौकरी की पहचान करती है bash
। bash
जॉब नंबर से पहले '%' साइन अप करने वाले कमांड में निर्मित हम निम्न में उपयोग कर सकते हैं :
$ 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>
मुझे उम्मीद है कि यह समाधान का एक पूर्ण विवरण है।
lsof
(फ़ाइल हैंडल का नाम ऐसा pipe
नहीं है /dev/pts/1
) या द्वारा ls -l /proc/<PID>/fd/<fd>
(यह हैंडल के सिम्लिंक को दर्शाता है)। इसके अलावा सबप्रोसेस में अभी भी रीडायरेक्ट किए गए आउटपुट नहीं हो सकते हैं, जिन्हें किसी फाइल में रीडायरेक्ट किया जाना चाहिए।
Nohup ( http://en.wikipedia.org/wiki/Nohup ) को रनिंग प्रक्रिया भेजने के लिए
nohup -p pid
, यह मेरे लिए काम नहीं किया
फिर मैंने निम्नलिखित आदेशों को आजमाया और यह बहुत अच्छा काम किया
कुछ SOMECOMMAND चलाएं, कहते हैं /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
।
Ctrl+ Zकार्यक्रम को रोकने (रोकने) और वापस शेल में जाने के लिए।
bg
इसे पृष्ठभूमि में चलाने के लिए।
disown -h
टर्मिनल बंद होने पर प्रक्रिया को नहीं मारा जाता है।
exit
शेल से बाहर निकलने के लिए टाइप करें क्योंकि अब आप जाने के लिए अच्छा है क्योंकि ऑपरेशन अपनी प्रक्रिया में पृष्ठभूमि में चलेगा, इसलिए यह शेल से बंधा नहीं है।
यह प्रक्रिया चलने के बराबर है nohup SOMECOMMAND
।
bg
- यह काम को पृष्ठभूमि में रखेगा और चलने की प्रक्रिया में वापस लौटेगाdisown -a
- यह नौकरी के साथ सभी लगाव में कटौती करेगा (इसलिए आप टर्मिनल को बंद कर सकते हैं और यह अभी भी चलेगा)ये सरल चरण आपको प्रक्रिया को चालू रखते हुए टर्मिनल को बंद करने की अनुमति देंगे।
यह nohup
आपके प्रश्न की मेरी समझ के आधार पर नहीं लगाया जाएगा , आपको इसकी आवश्यकता नहीं है)।
yourExecutable &
और आउटपुट स्क्रीन पर आते रहें औरCtrl+C
कुछ भी बंद न हो, बस आँख बंद करके टाइप करेंdisown;
औरEnter
स्क्रीन को आउटपुट के साथ स्क्रॉल करने पर भी दबाएँ और आप यह नहीं देख सकते कि क्या आप टाइप कर रहे हैं। यह प्रक्रिया समाप्त हो जाएगी और आप बिना प्रक्रिया के मरने के बाद टर्मिनल को बंद कर पाएंगे।