Ctrl-C बैश में एक साथ दो कमांड्स के साथ


15

मैं एक लिनक्स मशीन पर बैश में एक साथ दो कमांड चलाना चाहता हूं। इसलिए मेरी ./execute.shबैश स्क्रिप्ट में मैंने:

command 1 & command 2
echo "done"

हालाँकि जब मैं बैश स्क्रिप्ट को रोकना चाहता हूं और Ctrl+ मारा जाता है C, तो केवल दूसरी कमांड बंद हो जाती है। पहली आज्ञा चलती रहती है। मैं यह कैसे सुनिश्चित करूं कि पूरी बैश स्क्रिप्ट बंद हो जाए? या किसी भी मामले में, मैं दोनों आदेशों को कैसे रोकूं? क्योंकि इस मामले में कोई बात नहीं कि मैं कितनी बार दबाता हूं Ctrl+ Cकमांड चलती रहती है और मुझे टर्मिनल बंद करने के लिए मजबूर किया जाता है।


एक अलग प्रश्न में अनुवर्ती प्रश्न बनाएं और यहां निकालें। अब यह एक आगंतुक के लिए अस्पष्ट है यदि दोनों प्रश्न का उत्तर दिया गया था, या केवल अंतरंग प्रश्न।
ज़ेल्डा

जवाबों:


17

यदि आप टाइप करते हैं

command 1 & command 2

यह बराबर है

command 1 &
command 2

यानी यह पहले कमांड को बैकग्राउंड में चलाएगा और फिर फोरग्राउंड में दूसरी कमांड को रन करेगा। विशेष रूप से इसका मतलब है, कि आपका echo "done"प्रिंट command 2खत्म हो गया है भले ही command 1वह अभी भी चल रहा हो।

आप शायद चाहते हैं

command 1 &
command 2 &
wait
echo "done"

यह पृष्ठभूमि में दोनों कमांड चलाएगा और दोनों के पूरा होने की प्रतीक्षा करेगा।


यदि आप CTRL-C दबाते हैं तो यह केवल SIGINT सिग्नल को अग्रभूमि प्रक्रिया में भेजेगा, अर्थात command 2आपके संस्करण में या waitमेरे संस्करण में।

मैं इस तरह एक जाल स्थापित करने का सुझाव दूंगा:

#!/bin/bash

trap killgroup SIGINT

killgroup(){
  echo killing...
  kill 0
}

loop(){
  echo $1
  sleep $1
  loop $1
}

loop 1 &
loop 2 &
wait

जाल के साथ CTRL-C द्वारा निर्मित SIGINT सिग्नल फंस गया है और killgroupफ़ंक्शन द्वारा प्रतिस्थापित किया गया है, जो उन सभी प्रक्रियाओं को मारता है।


आपके उत्तर के लिए धन्यवाद! हालाँकि मेरे पास एक अनुवर्ती प्रश्न है। अब मेरे पास निम्न स्क्रिप्ट है: ट्रैप किलग्रुप SIGINT किलग्रेप () {इको किलिंग ... किल 0} कमांड001 कमांड 1 & कमांड 2 मैंने वेट कमांड को हटा दिया है क्योंकि कमांड 2 समाप्त होने पर स्क्रिप्ट को जारी रखने की अनुमति है। हालाँकि ऐसा लगता है कि जब मैं स्क्रिप्ट चलाता हूं तो कमांड 1 पहले से ही शुरू हो जाता है। क्या मैं इसे ठीक कर सकता हूं? धन्यवाद
maero21

कमांड 1 समाप्त होने के बाद कमांड 1 सीधे शुरू होता है। आप set -xअपनी स्क्रिप्ट की शुरुआत में उन कमांड को प्रिंट करने के लिए उपयोग कर सकते हैं जो निष्पादित हैं।
माइक्स

6

स्क्रिप्ट से बैकग्राउंड में कमांड डालते समय, PID को स्क्रीन पर प्रदर्शित नहीं किया जाता है। आप अंतर्निहित चर का उपयोग कर सकते हैं$! जो अंतिम प्रक्रिया के पीआईडी ​​को संग्रहीत करता है ताकि आप कमांड 1 के पीआईडी ​​को पकड़ सकें।

command1 &
echo $!

कमांड 1 के पीआईडी ​​को प्रतिध्वनित करेगा।

बैश ट्रैप बिलिन भी प्रदान करता है जिसका उपयोग आप विशेष सिग्नल प्राप्त होने पर चलाने के लिए आदेशों के अनुक्रम को पंजीकृत करने के लिए कर सकते हैं। आप इसका उपयोग मुख्य स्क्रिप्ट से बाहर निकलने से पहले SIGINT को पकड़ने और कमांड 1 को मारने के लिए कर सकते हैं

#!/bin/bash

onINT() {
echo "Killing command1 $command1PID too"
kill -INT "$command1PID"
exit
}

trap "onINT" SIGINT
command1 &
command1PID="$!"
comamnd2
echo Done

अब, जबकि कमांड 2 चल रहा है, मारने Ctrl Cसे कमांड 1 और कमांड 2 दोनों को SIGINT भेजा जाएगा।


आप %nइस शेल में विशिष्ट पृष्ठभूमि नौकरियों को मारने के लिए सिंटैक्स का उपयोग कर सकते हैं । आमतौर पर आप kill %1नवीनतम और एकमात्र पृष्ठभूमि प्रक्रिया को मारने के लिए जारी करते हैं। अधिक पृष्ठभूमि प्रक्रियाओं के साथ, jobsपहले सूची देखने के लिए उपयोग करें।
9000

@ 9000: हाँ, लेकिन ओपी एक स्क्रिप्ट (./execute.sh) में अपनी कमांड चला रहा है, इसलिए काम करने के लिए नौकरी मिलना निश्चित रूप से अधिक समस्याग्रस्त है?

@ सादा: निश्चित रूप से। मुझे स्क्रिप्ट से भाग जाने की बात याद आ गई।
9000

5

GNU समानांतर के नए संस्करण वही करेंगे जो आप चाहते हैं:

parallel ::: "command 1" "command 2"
echo "done"

या यदि commandऐसा ही रहता है:

parallel command ::: 1 2
echo done

त्वरित परिचय के लिए परिचय वीडियो देखें: देखें https://www.youtube.com/playlist?list=PL284C9FF2488BC6V1

ट्यूटोरियल के माध्यम से चलो (आदमी समानांतर_tutorial)। आप इसके लिए आपको प्यार से आज्ञा दें।


1

Ctrl+ Cआपके सामने की प्रक्रिया के लिए एक संकेत संकेत भेजता है, जो है command2command1पृष्ठभूमि में चलाया जाता है, इसलिए इनपुट स्ट्रीम से चिंतित नहीं हैं।

जब आप टाइप करते हैं command1 &, तो बैश आपको प्रक्रिया 'PID, कुछ इस तरह देनी चाहिए [1234]। इस प्रक्रिया को मारने के लिए, आप उपयोग कर सकते हैं kill 1234। अब, यदि आपके पास दोनों के पीआईडी ​​हैं ( command1और command2एक नज़र डालें ps -ef), तो आप killउन सभी को समाप्त करने के लिए उपयोग कर सकते हैं :

kill pid1 pid2 pid3 ...

पृष्ठभूमि में दोनों कमांड चलाने के लिए एक छोटी सी चाल होगी:

command1 & command2 &

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

command1 & command2
# Hit Ctrl+C : command2 terminates.

fg # Bring back command1 to foreground.
# Hit Ctrl+C again, command1 terminates.

अधिक जानकारी यहाँ उपलब्ध है: http://linuxg.net/how-to-manage-background-and-foreground-processes/

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