मैं लिनक्स के तहत निलंबित स्थिति में एक प्रक्रिया कैसे शुरू करूं?


19

व्यावहारिक रूप से, मुझे एक ऐसी प्रक्रिया की आवश्यकता है जो व्यवहार करती है, जैसे कि मैंने Ctrl+Zइसे शुरू करने के बाद दबाया था ।

उम्मीद है, शेल स्क्रिप्ट का उपयोग करके ऐसा करना संभव है।

(इसके अलावा, परिणामी पीआईडी ​​को जानना बहुत अच्छा होगा, इसलिए मैं बाद में प्रक्रिया जारी रख सकता हूं।)

जवाबों:


7

एक प्रक्रिया शुरू करने के बाद, आप इसे निलंबित करने के लिए इसे SIGSTOP भेज सकते हैं। इसे फिर से शुरू करने के लिए, SIGCONT भेजें। मुझे लगता है कि यह छोटी स्क्रिप्ट आपकी मदद कर सकती है

#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID

यह प्रक्रिया चलाता है (पैरामीटर के रूप में कमांड भेजता है), इसे निलंबित करता है, आईडी को प्रोसेस करता है और समाप्त होने तक प्रतीक्षा करता है।


1
मैंने इसे अंत में जारी रखने के लिए संशोधित किया: [दर्ज करें] #!/bin/bash [दर्ज करें] $@ & [दर्ज करें] PID=$! [दर्ज करें] kill -STOP $PID [दर्ज करें] echo "Suspended: $PID, press ENTER to continue it" [दर्ज करें] read [दर्ज करें] kill -CONT $PID [दर्ज करें] wait $PID [दर्ज करें]echo
java.is.for.desktop

7
बस इतना पता है, इससे पहले कि आप को STOP सिग्नल भेजने का मौका मिले, सबप्रोसेस खत्म हो जाए।
मिकीबी जूल

16
दौड़ में एक और दिन।
ctrl-alt-delor-

23

आप किस वातावरण से प्रक्रिया बना रहे हैं?

यदि आप इसे C कोड जैसे वातावरण से कर रहे हैं, तो आप कांटा () और फिर बच्चे में, निष्पादन से पहले खुद को एक SIGSTOP भेज सकते हैं (), और निष्पादन को रोक सकते हैं।

एक अधिक सामान्य समाधान (शायद सबसे अच्छा) एक स्टब बनाने के लिए होगा जो ऐसा करता है। तो ठूंठ कार्यक्रम होगा:

  • वास्तविक कार्यक्रम के नाम और तर्कों से युक्त तर्क लें
  • खुद को एक हस्ताक्षर भेजें
  • निष्पादन () उचित तर्कों के साथ वास्तविक कार्यक्रम

यह सुनिश्चित करेगा कि आप किसी भी प्रकार की दौड़ की स्थिति से बचने के लिए नए प्रसंस्करण के साथ बहुत दूर हो रहे हैं इससे पहले कि आप इसे एक संकेत भेज सकें।


शेल के लिए एक उदाहरण:

#!/bin/bash
kill -STOP $$
exec "$@"

और ऊपर दिए गए कोडज़ का उपयोग करना:

michael@challenger:~$ ./stopcall.sh ls -al stopcall.sh

[1]+  Stopped                 ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ jobs -l
[1]+ 23143 Stopped (signal)        ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ kill -CONT 23143; sleep 1
-rwxr-xr-x 1 michael users 36 2011-07-24 22:48 stopcall.sh
[1]+  Done                    ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ 

jobs -lपीआईडी को दर्शाता है। लेकिन अगर आप इसे एक शेल से कर रहे हैं तो आपको सीधे पीआईडी ​​की आवश्यकता नहीं है। आप बस कर सकते हैं: kill -CONT %1(यह मानते हुए कि आपके पास केवल एक ही काम है)।

यह एक से अधिक काम के साथ कर? पाठक के लिए एक अभ्यास के रूप में छोड़ दिया :)


मैं इसे शेल स्क्रिप्ट से करने की उम्मीद कर रहा था ...
java.is.for.desktop

महान, इसलिए चूंकि आप इसे शेल स्क्रिप्ट से करना चाहते हैं, स्टब प्रोग्राम का उपयोग करें।
मिकीबी

20

मिकीबी का जवाब सही है। सुपरसुसर पर इस सवाल से , यहां एक अधिक संक्षिप्त संस्करण है:

( kill -SIGSTOP $BASHPID; exec my_command ) &

इसे समझने के लिए, यह समझने की आवश्यकता है कि यूनिक्स पर प्रक्रियाएं कैसे शुरू होती हैं: execसिस्टम कॉल वर्तमान में चल रहे प्रोग्राम को एक नए के साथ बदल देता है , जो मौजूदा पीआईडी ​​को संरक्षित करता है। तो जिस तरह से एक स्वतंत्र प्रक्रिया बनाई जाती है fork, वह पहले , और फिर exec, वांछित कार्यक्रम के साथ बच्चे की प्रक्रिया में चल रहे प्रोग्राम को बदलना है।

इस शेल कमांड के घटक हैं:

  1. कोष्ठक (...)एक उप-खोल शुरू करते हैं: BASH का एक और उदाहरण।
  2. killआदेश में इस प्रक्रिया को, जो इसे निलंबित अवस्था में रखता है के लिए STOP संकेत भेजता है।
  3. जैसे ही आप प्रक्रिया को जारी रखने की अनुमति देते हैं (इसे CONTसंकेत भेजकर ), execकमांड इसे आपके वांछित कार्यक्रम के साथ बदलने का कारण बनता है । my_commandउप-शेल का मूल पीआईडी ​​रखता है।
  4. $!प्रक्रिया के पीआईडी ​​प्राप्त करने के लिए आप चर का उपयोग कर सकते हैं ।

2
मुझे यह पसंद है, क्योंकि यह मौलिक रूप से सही है (बस -s STOPइसके बजाय मुझे इसका उपयोग करना था -SIGSTOP)। अभी भी आश्चर्य: $BASHPIDइसके बजाय क्यों होना है $$? (मैं वास्तव में अंतर नहीं समझ सकता हूं)।
हिबू ५ H

1
के लिए $$बनाम $BASHPID, मैं जाँच बाद उप खोल के पीआईडी है, जबकि पूर्व नहीं। एक मज़ेदार मुद्दा है: टिप को बैश स्क्रिप्ट में लागू करना, सबसे अधिक बार विफल होता है, और मुझे ऐसा कुछ करना होगा: PID=$!; ps -p $PID; kill -s CONT $PID;... यह विफल हो जाता है अगर मैं ps -p $PIDभाग को हटा देता हूं : प्रक्रिया कहीं भी त्रुटि संदेश के बिना गायब हो गई (मार दी गई) लगती है? । यह एक इंटरैक्टिव शेल से ठीक है, मुद्दा केवल स्क्रिप्ट से है। यह बहुत रहस्यमय है।
हिबू ५।

मैंने my_command के फ़ाइल डिस्क्रिप्टर को सूचीबद्ध करने के लिए इस समाधान का उपयोग करने का प्रयास किया। ( goo.gl/cNbUE8 ), लेकिन वर्णनकर्ता अभी भी वही नहीं हैं, जो कि my_command है।
रास्टी। जी

$BASHPIDबैश के अलावा अन्य गोले को बदलने के विकल्पों के लिए , यहां
जैकब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.