कई कमांड चलाएं और उन्हें बैश में मार दें


51

मैं एक शेल पर कई कमांड (प्रक्रियाएं) चलाना चाहता हूं। उन सभी के पास अपना निरंतर उत्पादन है और रुकना नहीं है। पृष्ठभूमि में उन्हें चलाने से टूट जाता है Ctrl- C। मैं उन्हें एक ही प्रक्रिया के रूप में चलाना चाहता हूं (उपधारा, शायद?) उन सभी को रोकने में सक्षम होना चाहिए Ctrl- C

विशिष्ट होने के लिए, मैं mocha(वॉच मोड) के साथ यूनिट टेस्ट चलाना चाहता हूं , सर्वर चलाना और कुछ फाइल प्रीप्रोसेसिंग (वॉच मोड) चलाना और एक टर्मिनल विंडो में प्रत्येक का आउटपुट देखना चाहता हूं। मूल रूप से मैं कुछ टास्क रनर के इस्तेमाल से बचना चाहता हूं।

मैं इसे पृष्ठभूमि में प्रक्रियाओं को चलाकर महसूस कर सकता हूं ( &), लेकिन फिर मुझे उन्हें रोकने के लिए अग्रभूमि में रखना होगा। मैं उन्हें लपेटने के लिए एक प्रक्रिया रखना चाहता हूं और जब मैं इस प्रक्रिया को रोक देता हूं तो वह अपने 'बच्चों' को रोक देती है।


क्या उन्हें समवर्ती रूप से चलना चाहिए या एक के बाद एक?
Minix

हां, प्रक्रियाओं को समवर्ती रूप से चलना चाहिए, लेकिन मुझे प्रत्येक से आउटपुट देखने की जरूरत है।
user1876909

जवाबों:


67

समवर्ती कमांड चलाने के लिए आप &कमांड सेपरेटर का उपयोग कर सकते हैं ।

~$ command1 & command2 & command3

यह शुरू होगा command1, फिर इसे पृष्ठभूमि में चलाता है। साथ ही command2। फिर यह command3सामान्य रूप से शुरू होता है।

सभी कमांड के आउटपुट को एक साथ जोड़ा जाएगा, लेकिन अगर यह आपके लिए कोई समस्या नहीं है, तो इसका समाधान होगा।

यदि आप बाद में आउटपुट पर एक अलग नज़र रखना चाहते हैं, तो आप प्रत्येक कमांड के आउटपुट को पाइप कर सकते हैं tee, जिससे आप आउटपुट को मिरर करने के लिए एक फ़ाइल निर्दिष्ट कर सकते हैं।

~$ command1 | tee 1.log & command2 | tee 2.log & command3 | tee 3.log

आउटपुट शायद बहुत गन्दा होगा। इसका मुकाबला करने के लिए, आप प्रत्येक कमांड के आउटपुट को एक उपसर्ग का उपयोग करके दे सकते हैं sed

~$ echo 'Output of command 1' | sed -e 's/^/[Command1] /' 
[Command1] Output of command 1

इसलिए यदि हम सबको एक साथ रखते हैं:

~$ command1 | tee 1.log | sed -e 's/^/[Command1] /' & command2 | tee 2.log | sed -e 's/^/[Command2] /' & command3 | tee 3.log | sed -e 's/^/[Command3] /'
[Command1] Starting command1
[Command2] Starting command2
[Command1] Finished
[Command3] Starting command3

यह एक उच्च आदर्श संस्करण है जिसे आप शायद देखने जा रहे हैं। लेकिन इसका सबसे अच्छा मैं अभी सोच सकता हूँ।

यदि आप एक बार में उन सभी को रोकना चाहते हैं, तो आप बिल्ड का उपयोग कर सकते हैं trap

~$ trap 'kill %1; kill %2' SIGINT
~$ command1 & command2 & command3

यह निष्पादित करेगा command1और command2पृष्ठभूमि command3में और अग्रभूमि में, जो आपको इसे Ctrl+ से मारने की सुविधा देता है C

जब आप अंतिम प्रक्रिया को Ctrl+ Cके साथ मारते हैं, तो kill %1; kill %2कमांड निष्पादित होते हैं, क्योंकि हमने उनके निष्पादन को एक इंट्रुप्ट सिगनल के रिसेप्शन के साथ जोड़ा, जो कि Ctrl+ दबाकर भेजी गई चीज है C

वे क्रमशः 1 और 2 की पृष्ठभूमि प्रक्रिया (आपके command1और command2) को मारते हैं । जाल को हटाने के लिए मत भूलना, के बाद आप अपने आदेश का उपयोग कर समाप्त कर रहे हैं trap - SIGINT

एक कमांड का पूरा राक्षस:

~$ trap 'kill %1; kill %2' SIGINT
~$ command1 | tee 1.log | sed -e 's/^/[Command1] /' & command2 | tee 2.log | sed -e 's/^/[Command2] /' & command3 | tee 3.log | sed -e 's/^/[Command3] /'

बेशक, आप स्क्रीन पर एक नजर डाल सकते हैं । यह आपको अपने कंसोल को जितने चाहें अलग कंसोल में विभाजित करने देता है। तो आप सभी कमांड को अलग से देख सकते हैं, लेकिन एक ही समय में।


3
सभी आलोचनाओं का इंतजार कर रहे हैं। :)
मिनिक्स

2
धन्यवाद। यह वही करता है जो मैं चाहता था (ट्रैप कमांड)। समाधान को पुन: प्रयोज्यता के लिए स्क्रिप्ट में लपेटा जाना चाहिए।
user1876909

@ user1876909 यहां एक कंकाल है। बारीकियों आप पर निर्भर हैं [1]। मैं खुशी से मदद कर सकता है। [१] pastebin.com/jKhtwF40
मिनिक्स

3
यह एक बहुत ही चतुर समाधान है, iv ने कुछ नया सीखा, ब्रावो +1
माइक-एम

1
ये अद्भुत है। मेरे पास इस उत्तर से खुदाई करने और सीखने के लिए बहुत कुछ है।
ccnokes

20

यदि आप एक ही प्रक्रिया समूह में उन्हें (और केवल उन्हें) चलाने की व्यवस्था करते हैं तो आप आसानी से प्रक्रियाओं का एक गुच्छा मार सकते हैं ।

लिनक्स setsidएक नई प्रक्रिया समूह में एक कार्यक्रम चलाने के लिए उपयोगिता प्रदान करता है (एक नए सत्र में, यहां तक ​​कि, लेकिन हम उस बारे में परवाह नहीं करते हैं)। (यह उल्लेखनीय है, लेकिन बिना अधिक जटिल हैsetsid ।)

प्रक्रिया समूह की प्रक्रिया समूह आईडी (PGID) समूह में मूल मूल प्रक्रिया की प्रक्रिया आईडी है। एक प्रक्रिया समूह में सभी प्रक्रियाओं को मारने के लिए, killसिस्टम कॉल या कमांड में पीजीआईडी ​​के नकारात्मक को पास करें। यदि पीआईडी ​​के साथ मूल प्रक्रिया मर जाती है (हालांकि यह थोड़ा भ्रमित हो सकता है) तो पीजीआईडी ​​वैध रहती है।

setsid sh -c 'command1 & command2 & command3' &
pgid=$!
echo "Background tasks are running in process group $pgid, kill with kill -TERM -$pgid"

यदि आप गैर-संवादात्मक शेल से पृष्ठभूमि में प्रक्रियाएं चलाते हैं , तो वे सभी शेल के प्रक्रिया समूह में बने रहेंगे। यह केवल इंटरैक्टिव गोले में है जो पृष्ठभूमि प्रक्रियाएं अपने स्वयं के प्रक्रिया समूह में चलती हैं। इसलिए, यदि आप एक गैर-संवादात्मक शेल से कमांडों को कांटा करते हैं जो अग्रभूमि में रहता है, Ctrl+ Cउन सभी को मार देगा। waitसभी कमांड के बाहर निकलने के लिए शेल को प्रतीक्षा करने के लिए बिलिन का उपयोग करें ।

sh -c 'command1 & command2 & command3 & wait'
# Press Ctrl+C to kill them all

2
अपरिभाषित उत्तर (नीचे की ओर विधि)। समझने और याद रखने में सरल।
निकोलस मार्शल

14

मुझे आश्चर्य है कि यह अभी तक यहाँ नहीं है, लेकिन ऐसा करने का मेरा पसंदीदा तरीका पृष्ठभूमि कमांड के साथ उप-भागों का उपयोग करना है । उपयोग:

(command1 & command2 & command3)

आउटपुट दोनों से दिखाई देता है, सभी बैश कमांड और उपयुक्तताएं अभी भी उपलब्ध हैं, और एक एकल Ctrl-cउन सभी को मारता है। मैं आमतौर पर एक ही समय में लाइव-डिबगिंग क्लाइंट फ़ाइल सर्वर और बैकएंड सर्वर शुरू करने के लिए इसका उपयोग करता हूं, इसलिए जब मैं चाहता हूं तो मैं उन दोनों को आसानी से मार सकता हूं।

जिस तरह से यह काम करता है वह है command1और command2एक नए उप-उदाहरण की पृष्ठभूमि में चल रहा है, और command3उस उदाहरण के अग्रभूमि में है, और उप-भाग वह है जो सबसे पहले एक Ctrl-cकीपर से किल संकेत प्राप्त करता है । यह बहुत पसंद है कि कौन किस प्रक्रिया का मालिक है और कब बैकग्राउंड प्रोग्राम मार दिए जाते हैं।


यदि आप waitअंतिम कमांड (आपके उदाहरण में कमांड 3) के रूप में जोड़ते हैं , तो आप उपयोगकर्ता को Ctrl-c दबाने के बाद क्लीन अप कोड निष्पादित कर सकते हैं ।
डॉटनेटकार्टेंटर

0

आप अर्धविराम ;या &&इस तरह का उपयोग कर सकते हैं :

cmd1; cmd2   # Runs both the commands, even if the first one exits with a non-zero status.

cmd1 && cmd2 # Only runs the second command if the first one was successful.

यह समवर्ती रूप से कमांड नहीं चलाता है।
गिल्स एसओ- बुराई को रोकना

-2

आप एक का उपयोग कर सकते हैं pipe। यह एक ही समय में पाइप के दोनों सिरों पर कमांड शुरू करेगा। आपको सभी कमांड को CTRL-Cभी बंद करने में सक्षम होना चाहिए ।

1st command | 2nd command | 3rd command

यदि आप एक के बाद एक कमांड चलाना चाहते हैं, तो आप @ सेरेनेट की विधि का उपयोग कर सकते हैं।


यह पहले कमांड के आउटपुट को दूसरे (और इसी तरह) पास करता है, जो कि यहाँ उचित नहीं है क्योंकि पहले कमांड का आउटपुट टर्मिनल पर समाप्त होने वाला है।
गिल्स एसओ- बुराई को रोकना
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.