कमांड निष्पादन के बाद बैश को कैसे रखा जाए?


29

मैं कुछ इस तरह से दौड़ना चाहूंगा:

bash -c "some_program with its arguments"

लेकिन अंतःक्रियात्मक बैश some_programसमाप्त होने के बाद भी चलते रहना चाहिए ।

मुझे यकीन है कि seys के -cरूप में एक अच्छा तरीका नहीं है man bash:

एक इंटरैक्टिव शेल गैर-विकल्प तर्क के बिना और -c विकल्प के बिना शुरू किया गया है

तो यह कैसे करना है?

मुख्य लक्ष्य यहाँ वर्णित है

ध्यान दें

  • मुझे some_programसमय-समय पर समाप्त करने की आवश्यकता है
  • मैं इसे पृष्ठभूमि में नहीं रखना चाहता
  • मैं bashकुछ और करने के लिए तत्कालीन समय पर बने रहना चाहता हूं
  • मैं फिर से कार्यक्रम चलाने में सक्षम होना चाहता हूं

1
यदि लक्ष्य इतना जटिल है, तो आपको इसे यहाँ भी समझाना चाहिए। लेकिन यह सिर्फ एक सलाह है
किवी

1
मैंने यहां यथासंभव संक्षिप्त और बहुत सटीक रूप से वर्णन करने का प्रयास किया। लेकिन मुझे उम्मीद नहीं थी कि अधिकांश लोग विवरणों पर ध्यान केंद्रित नहीं करेंगे और कुछ और प्रस्तावित करने का प्रयास करेंगे। मैं इसे स्पष्ट करने के लिए कुछ नोट रखूंगा।
pawel7318

उस अन्य प्रश्न के लिए टर्मिनल क्या हैं? आपके द्वारा वर्णित लक्ष्य उल्लेखनीय है, लेकिन इसके लिए i / o को संभालने की आवश्यकता होगी। आपका औसत सबस्क्रिप्शन आसानी से एक नियमित फ़ाइल के माध्यम से बच गए टर्मिनल i / o को संभालने के लिए नहीं जा रहा है। आपको देखना चाहिएpty.
mikeserv

नीचे दिए गए मेरे जवाब में एक ही कारण है, वैसे, क्योंकि मैं टर्मिनल चुरा रहा हूं। आखिरकार, हालांकि, मूल प्रक्रिया को वापस लेने की संभावना है - और फिर आप 4kb बफ़र देख रहे हैं।
मिकसेर्व

आप पृष्ठभूमि में एक कार्यक्रम क्यों नहीं रखना चाहते हैं? इसे पृष्ठभूमि में शुरू करें, कुछ बैश करें, इसे अग्रभूमि पर रखेंfg
बर्नहार्ड

जवाबों:


8
( exec sh -i 3<<SCRIPT 4<&0 <&3                                        
    echo "do this thing"
    echo "do that thing"
  exec  3>&- <&4
  SCRIPT
)

यह एक स्क्रिप्ट से बेहतर है, हालांकि exec $0.या अगर उन फ़ाइल डिस्क्रिप्टर में से कोई एक टर्मिनल डिवाइस को निर्देश देता है जिसका वर्तमान में उपयोग नहीं किया जा रहा है तो इससे मदद मिलेगी - आपको याद होगा, अन्य प्रक्रियाएं उस टर्मिनल की भी जांच करना चाहती हैं।

और वैसे, यदि आपका लक्ष्य है, जैसा कि मैंने माना है कि स्क्रिप्ट के पर्यावरण को संरक्षित करने के लिए, इसे निष्पादित करने के बाद, आप शायद इसके साथ बेहतर सेवा करेंगे:

. ./script

खोल के .dotऔर bash's sourceनहीं एक और एक ही कर रहे हैं - खोल के .dotPOSIX एक विशेष खोल अंतर्निहित रूप में निर्दिष्ट किया है और के रूप में पास की गारंटी की जा रही के रूप में आप प्राप्त कर सकते हैं करने के लिए इसलिए है, हालांकि यह किसी भी तरह से एक गारंटी यह वहाँ हो जाएगा ...

यद्यपि उपरोक्त आपको कम मुद्दे के साथ अपेक्षा के अनुसार करना चाहिए। उदाहरण के लिए, आप कर सकते हैं:

 ( exec sh -i 3<<SCRIPT 4<&0 <&3                                        
    echo "do this thing"
    echo "do that thing"
    $(cat /path/to/script)
    exec  3>&- <&4
    SCRIPT
 )

शेल आपकी स्क्रिप्ट को चलाएगा और आपको इंटरेक्टिव प्रॉम्प्ट पर लौटाएगा - इसलिए जब तक आप exitअपनी स्क्रिप्ट से शेल से बचते हैं, अर्थात, या अपनी प्रक्रिया को बैकग्राउंड करते हैं - जो आपके i / o को लिंक करेगा/dev/null.

डेमो:

% printf 'echo "%s"\n' "These lines will print out as echo" \
    "statements run from my interactive shell." \
    "This will occur before I'm given the prompt." >|/tmp/script
% ( exec sh -i 3<<SCRIPT 4<&0 <&3
    echo "do this thing"
    echo "do that thing"
    $(cat /tmp/script)
    exec  3>&- <&4
SCRIPT
)
sh-4.3$ echo "do this thing"
    do this thing
sh-4.3$ echo "do that thing"
    do that thing
sh-4.3$ echo "These lines will print out as echo"
    These lines will print out as echo
sh-4.3$ echo "statements run from my interactive shell."
    statements run from my interactive shell.
sh-4.3$ echo "This will occur before I'm given the prompt."
    This will occur before I'm given the prompt.
sh-4.3$ exec  3>&- <&4
sh-4.3$

अनेक JOBS

यह मेरी राय है कि आपको शेल के अंतर्निहित कार्य प्रबंधन विकल्पों से थोड़ा अधिक परिचित होना चाहिए। @Kiwy और @jillagre ने पहले ही अपने उत्तर में दोनों को छुआ है, लेकिन यह आगे विस्तार से वारंट कर सकता है। और मैंने पहले ही एक POSIX- निर्दिष्ट विशेष शेल बिल्ट-इन का उल्लेख किया है, लेकिनset, jobs, fg, और bgकुछ और हैं, और, के रूप में एक और उत्तर को दर्शाता है trapऔर killअधिक अभी भी दो हैं।

यदि आप पहले से ही समवर्ती पृष्ठभूमि वाली प्रक्रियाओं की स्थिति पर त्वरित सूचनाएं प्राप्त नहीं कर रहे हैं, तो यह इसलिए है क्योंकि आपके वर्तमान शेल विकल्प POSIX- निर्दिष्ट डिफ़ॉल्ट के लिए सेट हैं -m, लेकिन आप set -bइसके बजाय इन अतुल्यकालिक रूप से प्राप्त कर सकते हैं :

% man set
    b This option shall be supported if the implementation supports the
         User  Portability  Utilities  option. It shall cause the shell to
         notify the user asynchronously of background job completions. The
         following message is written to standard error:
             "[%d]%c %s%s\n", <job-number>, <current>, <status>, <job-name>

         where the fields shall be as follows:

         <current> The  character  '+' identifies the job that would be
                     used as a default for the fg or  bg  utilities;  this
                     job  can  also  be specified using the job_id "%+" or
                     "%%".  The character  '−'  identifies  the  job  that
                     would  become  the default if the current default job
                     were to exit; this job can also  be  specified  using
                     the  job_id  "%−".   For  other jobs, this field is a
                     <space>.  At most one job can be identified with  '+'
                     and  at  most one job can be identified with '−'.  If
                     there is any suspended  job,  then  the  current  job
                     shall  be  a suspended job. If there are at least two
                     suspended jobs, then the previous job also shall be a
   m  This option shall be supported if the implementation supports the
         User Portability Utilities option. All jobs shall be run in their
         own  process groups. Immediately before the shell issues a prompt
         after completion of the background job, a message  reporting  the
         exit  status  of  the background job shall be written to standard
         error. If a foreground job stops, the shell shall write a message
         to  standard  error to that effect, formatted as described by the
         jobs utility. In addition, if a job  changes  status  other  than
         exiting  (for  example,  if  it  stops  for input or output or is
         stopped by a SIGSTOP signal), the shell  shall  write  a  similar
         message immediately prior to writing the next prompt. This option
         is enabled by default for interactive shells.

यूनिक्स-आधारित प्रणालियों की एक बहुत ही मौलिक विशेषता प्रक्रिया को संभालने की उनकी विधि है signals। मैंने एक बार एक ज्ञानवर्धक लेख पढ़ा इस विषय पर डगलस एडम्स के ग्रह नोवेट के विवरण के लिए इस प्रक्रिया की तुलना करता है :

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

इस बात का जिक्र है kill signals

% kill -l 
> HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS

कम से कम मेरे लिए, उपरोक्त उद्धरण ने बहुत सारे सवालों के जवाब दिए। उदाहरण के लिए, मैं हमेशा इसे बहुत ही अजीब मानती थी और बिल्कुल भी सहज नहीं थी कि अगर मैं निगरानी करना चाहती थीdd प्रक्रिया की पड़ा kill। जिसे पढ़ने के बाद समझ में आया।

मैं कहूंगा कि उनमें से अधिकांश अनुकूलन करने की कोशिश नहीं करते हैं अच्छे कारण के - यह एक बड़ी गड़बड़ी हो सकती है, क्योंकि यह एक वरदान होगा प्रक्रियाओं का एक गुच्छा आपके टर्मिनल को स्पैम करने से जो भी जानकारी उनके डेवलपर्स के लिए आपके लिए महत्वपूर्ण हो सकती है। ।

आपके टर्मिनल कॉन्फ़िगरेशन (जो आप के साथ जांच कर सकते हैं stty -a) के आधार पर , CTRL+Zसंभावित रूप से SIGTSTPवर्तमान अग्रभूमि प्रक्रिया समूह के नेता को अग्रेषित करने के लिए सेट किया जाता है, जो आपके शेल की संभावना है, और जिसे डिफ़ॉल्ट रूप से trapउस सिग्नल से भी कॉन्फ़िगर किया जाना चाहिए और आपकी अंतिम कमांड को निलंबित करना चाहिए । फिर से, @jillagre और @Kiwy के जवाबों को एक साथ दिखाने के रूप में, इस कार्यक्षमता को अपने उद्देश्य के लिए पसंद करने पर आपको रोकना नहीं है।

SCREEN JOBS

इसलिए इन सुविधाओं का लाभ उठाने के लिए यह अपेक्षित है कि आप पहले उन्हें समझें और उनकी हैंडलिंग को अपनी आवश्यकताओं के अनुसार अनुकूलित करें। उदाहरण के लिए, मैंने सिर्फ Github पर यह स्क्रीन आर्क पाया है जिसमें इसके screenलिए की-बाइंडिंग शामिल है SIGTSTP:

# hitting 'C-z C-z' will run Ctrl+Z (SIGTSTP, suspend as usual)
bind ^Z stuff ^Z

# hitting 'C-z z' will suspend the screen client
bind z suspend

यह एक सरल बात होगी कि आप एक बाल screenप्रक्रिया के रूप में चल रही प्रक्रिया को स्थगित कर दें या screenबाल प्रक्रिया स्वयं आपकी इच्छानुसार हो।

और तुरंत बाद:

% fg  

या:

% bg

अपनी पसंद के अनुसार प्रक्रिया को अग्रभूमि या पृष्ठभूमि देगा। jobsमें निर्मित आप किसी भी समय इन की एक सूची प्रदान कर सकते हैं। -lओपेरंड को जोड़ने से पिड विवरण शामिल होगा।


बहुत दिलचस्प लग रहा है। मैं आज बाद में इसका सभी परीक्षण कर सकूंगा।
pawel7318

23

यहाँ एक छोटा समाधान है जो आप जो चाहते हैं उसे पूरा करता है, लेकिन जब तक आप समस्या को नहीं समझते हैं और कैसे काम करता है समझ में नहीं आता है:

bash -i <<< 'some_program with its arguments; exec </dev/tty'

यह एक बैश शेल लॉन्च करेगा, शुरू करेगा some_program, और उसके बादsome_program बाहर निकलने के , आपको बैश शेल में गिरा दिया जाएगा।

मूल रूप से हम जो कर रहे हैं, वह स्टेटिन पर एक स्ट्रिंग को खिला रहा है। वह तार है some_program with its arguments; exec </dev/tty। यह बैश को some_programपहले लॉन्च करने , और उसके exec </dev/ttyबाद चलाने के लिए कहता है । इसलिए हम इसे पास करने वाले स्ट्रिंग से कमांड पढ़ना जारी रखने के बजाय, बैश पढ़ना शुरू कर देंगे/dev/tty

-iक्योंकि जब पार्टी शुरू होता है, यह अगर STDIN एक tty है देखने के लिए जांच करता है, और जब यह शुरू होता है यह नहीं है। लेकिन बाद में यह होगा, इसलिए हम इसे इंटरैक्टिव मोड में लागू करते हैं।


एक और समाधान

एक अन्य विचार जो मुझे लगा कि यह बहुत ही पोर्टेबल होगा, यह आपकी ~/.bashrcफ़ाइल के अंत में निम्नलिखित को जोड़ना होगा ।

if [[ -n "START_COMMAND" ]]; then
  start_command="$START_COMMAND"
  unset START_COMMAND
  eval "$start_command"
fi

फिर जब आप पहले एक कमांड के साथ एक शेल लॉन्च करना चाहते हैं, तो बस करें:

START_COMMAND='some_program with its arguments' bash

स्पष्टीकरण:

इसमें से अधिकांश स्पष्ट होना चाहिए, लेकिन चर नाम बदलने वाले सामान के लिए अनुनाद इतना है कि हम चर को स्थानीय कर सकते हैं। चूंकि $START_COMMANDएक निर्यातित चर है, यह शेल के किसी भी बच्चे को विरासत में मिलेगा, और यदि कोई अन्य बैश शेल उन बच्चों में से एक है, तो यह फिर से कमांड चलाएगा। इसलिए हम एक नए unexported चर ( $start_command) के लिए मान असाइन करते हैं और पुराने को हटा देते हैं।


अगर वहाँ एक से अधिक है क्या उड़ा? एक आदेश? नहीं, अभी भी काम करना चाहिए। हालाँकि आप पोर्टेबिलिटी के बारे में सही हैं। वहाँ 2 कारक हैं, <<<POSIX नहीं है, लेकिन आप echo "string here" | bash -iइसके बजाय कर सकते हैं। फिर /dev/ttyजो है वो एक linux चीज़ है। लेकिन आप बैश लॉन्च करने से पहले एफडी को डंप कर सकते हैं, और फिर एसटीडीआईएन को फिर से खोल सकते हैं, जो कि आप क्या कर रहे हैं के समान दिखता है, लेकिन मैंने चीजों को सरल रखने का विकल्प चुना।
पैट्रिक

ओके ओके बस लड़ाई मत करो। यह सिर्फ मेरे लिए काम करता है और मुझे जो कुछ भी चाहिए वह करता है। मुझे POSIX और पोर्टेबिलिटी के बारे में ज्यादा परवाह नहीं है, मुझे अपने बॉक्स पर और केवल वहां इसकी आवश्यकता है। मैं mikeserv के उत्तर की जाँच करूँगा, लेकिन अब ऐसा नहीं कर सकता।
pawel7318

1
लड़ना नहीं :-)। मैं मिक्सर के जवाब का सम्मान करता हूं। वह अनुकूलता के लिए गया, मैं सरलता के लिए गया। दोनों पूरी तरह से वैध हैं। कभी-कभी अगर यह अत्यधिक जटिल नहीं है तो मैं संगतता के लिए जाऊंगा। इस मामले में मुझे नहीं लगा कि यह इसके लायक है।
पैट्रिक

2
@ पैट्रिक, /dev/ttyएक लिनक्स चीज नहीं है , लेकिन निश्चित रूप से पॉसिक्स है।
जुल्गेरे


8

यह काम कर जाना चाहिए:

bash -c "some_program with its arguments;bash"

संपादित करें:

आपके अपडेट के बाद एक नया प्रयास यहां दिया गया है:

bash -c "
trap 'select wtd in bash restart exit; do [ \$wtd = restart ] && break || \$wtd ; done' 2
while true; do
    some_program with its arguments
done
"
  • मुझे समय-समय पर कुछ_प्रोग्राम को समाप्त करने की आवश्यकता है

उपयोग करें ControlC, आपको यह छोटा मेनू प्रस्तुत किया जाएगा:

1) bash
2) restart
3) exit
  • मैं इसे पृष्ठभूमि में नहीं रखना चाहता

यही हाल है।

  • मैं बैश पर रहना चाहता हूं फिर कुछ और करना है

"बैश" विकल्प का चयन करें

  • मैं फिर से कार्यक्रम चलाने में सक्षम होना चाहता हूं

"पुनरारंभ" विकल्प चुनें


बुरा नहीं बुरा नहीं है .. लेकिन अच्छा होगा कि उस अंतिम आदेश पर वापस जाने में सक्षम हो। उसके लिए कोई विचार? मेरी एक और सवाल की जांच करें यहाँ क्या देखने के लिए मैं इसे जरूरत के लिए। तो शायद आप एक और दृष्टिकोण
सुझाएंगे

यह एक सबमिशन निष्पादित करता है। मुझे लगता है कि पूछने वाला स्क्रिप्ट के माहौल को बनाए रखने की कोशिश कर रहा है।
mikeserv

धन्यवाद jlliagre - अच्छा प्रयास है, लेकिन मेरे लिए बहुत उपयोगी नहीं है। मैं आमतौर पर ctrl + C दबाता हूं और मुझे उम्मीद है कि यह सिर्फ वही करेगा जो इसे करने के लिए लगता है। अतिरिक्त मेनू अभी बहुत है।
pawel7318

@ pawel7318 का व्यवहार CTRL+Cआपके टर्मिनल के डिफ़ॉल्ट कॉन्फ़िगरेशन का एक साइड-इफ़ेक्ट है, इसे एक के रूप में व्याख्या करने के लिए SIGINT। आप इसे अपने साथ संशोधित कर सकते हैं stty
mikeserv

@ pawel7318 आगे स्पष्ट करने के लिए, SIGINTहै trappedके साथ ऊपर 2
mikeserv

3

आप इसकी स्क्रिप्ट को इनिशियलाइज़ेशन फ़ाइल के रूप में पास करके कर सकते हैं:

bash --init-file foo.script

या आप इसे कमांड लाइन पर पास कर सकते हैं:

bash --init-file <(echo "ls -al")

ध्यान दें कि --init-fileसिस्टम वाइड इनिशियलाइज़ेशन फ़ाइलों को पढ़ने के लिए था, जैसे /etc/bash.bashrcकि आप sourceअपनी स्क्रिप्ट में इन्हें ' ' करना चाहते हैं ।


0

मैं वास्तव में ऐसा करने के बिंदु को नहीं देखता हूं, क्योंकि आप पहले से ही इस कार्यक्रम को चलाने के बाद एक शेल पर वापस जाते हैं। हालाँकि, आप ऐसा कर सकते हैं:

bash -c "some_program with its arguments; bash"

यह कार्यक्रम चलाने के बाद एक इंटरैक्टिव बैश लॉन्च करेगा।


यह एक सबमिशन लॉन्च करता है।
मोकेसर

0

आप अपने वर्तमान बैश को खुला रखने के लिए कमांड को पृष्ठभूमि में रख सकते हैं:

some_program with its arguments &

रनिंग पर लौटने के लिए आप फिर fgकमांड का उपयोग कर सकते हैं और ^+zइसे फिर से बैकग्राउंड में रख सकते हैं


इस समय नहीं। आप मान लें कि मैं इस बैश को चलाना चाहता हूं ... बैश से जो मामला नहीं है।
pawel7318

@ pawel7318 अगर आप थोड़ा और समझाएं तो हम आपको बेहतर जवाब दे सकते हैं?
कीवी

कृपया मेरे दूसरे प्रश्न को यहां देखें
pawel7318

@ pawel7318 यदि आपका प्रश्न संबंधित है तो कृपया अपने स्वयं के प्रश्न में अन्य प्रश्न का लिंक जोड़ें।
कीवी

1
@ pawel7318 bashया नहीं, आप एक बहुत ही विदेशी शेल का उपयोग कर रहे हैं अगर यह प्रक्रिया पृष्ठभूमि को संभाल नहीं सकता है। और मैं कीवी के साथ सहमत हूं - यह जानकारी आपको बेहतर सेवा प्रदान करेगी यदि यह आपके प्रश्न में है।
मोकेसर

0

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

वैकल्पिक रूप से, बस पृष्ठभूमि में कमांड चलाएं some_program with its arguments&। यह आपको कमांड को फिर से चलाने और कम्मंड की स्थिति प्राप्त करने की क्षमता को छोड़ देगा।


मैं इसे ठीक से चला रहा हूं, screenलेकिन इसे पृष्ठभूमि में रखना मेरे लिए उपयोगी नहीं है - मुझे कभी-कभी कार्यक्रम को समाप्त करने, कुछ और करने और इसे फिर से चलाने की आवश्यकता है। और इस व्रत को करना मुख्य लक्ष्य है।
pawel7318

@ pawel7318 आप पृष्ठभूमि प्रोग्राम को कमांड से मार सकते हैं kill %या kill %1
बिलथोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.