शेल स्क्रिप्ट को रोकने के लिए किसी भी कुंजी को दबाएं, फिर से शुरू करने के लिए फिर से दबाएं


11

मैंने एक एपीआई के परीक्षण के लिए एक शेल स्क्रिप्ट लिखी है जो फ़ाइलों को कॉपी करती है और प्रत्येक के बाद इसकी प्रगति को गूँजती है।

प्रत्येक कॉपी के बीच दो सेकंड की नींद है, इसलिए मैं गहराई से परीक्षण की अनुमति देने के लिए स्क्रिप्ट को रोकने के लिए किसी भी कुंजी को दबाने की क्षमता जोड़ना चाहूंगा। फिर से शुरू करने के लिए किसी भी कुंजी को दबाएं।

मैं इसे यथासंभव कुछ पंक्तियों में कैसे जोड़ सकता हूं?

जवाबों:


12

आपको अपनी स्क्रिप्ट में कुछ जोड़ने की आवश्यकता नहीं है। शेल ऐसी कार्यक्षमता की अनुमति देता है।

  • एक टर्मिनल में अपनी स्क्रिप्ट शुरू करें।
  • जबकि चल रहा है और टर्मिनल उपयोग को रोक रहा है ctrl- z। टर्मिनल को फिर से जारी किया जाता है और आपका संदेश दिखाई देता है कि प्रक्रिया बंद हो गई है। (यह अब पोर्स की अवस्था में है T, बंद हो गया)
  • अब तुम जो चाहो करो। तुम भी अन्य प्रक्रियाओं / लिपियों शुरू करने और उन लोगों के साथ बंद कर सकते हैं ctrl- z
  • jobsटर्मिनल में टाइप करें या सभी रोकी गई नौकरियों को सूचीबद्ध करें।
  • अपनी स्क्रिप्ट जारी रखने के लिए, टाइप करें fg(अग्रभूमि)। यह नौकरी को अग्रभूमि प्रक्रिया समूह में फिर से शुरू करता है और नौकरियां चलती रहती हैं।

एक उदाहरण देखें:

root@host:~$ sleep 10 # sleep for 10 seconds
^Z
[1]+  Stopped                 sleep 10
root@host:~$ jobs # list all stopped jobs
[1]+  Stopped                 sleep 10
root@host:~$ fg # continue the job
sleep 10
root@host:~$ # job has finished

जैसे आपने कहा, अगर मैं दौड़ता हूं sleep 10; notify-send helloऔर रोकने के लिए CTRL + Z दबाता हूं, तो notify-send helloनिष्पादित हो जाओ। यदि दूसरी कमांड निष्पादित हो रही है तो पहली प्रक्रिया को कैसे रोका जाए? उसके बाद अगर टाइप करें तो fgमैं कुछ भी होता हुआ नहीं देख सकता, जो कि स्पष्ट है, क्योंकि दूसरी कमान पहले ही निष्पादित हो चुकी है
एडवर्ड टोरवेल्स

@edwardtorvalds क्योंकि दोनों कमांड अलग-अलग हैं। एक स्क्रिप्ट में, वे एक उपधारा में होना चाहिए। उन्हें एक साधारण स्क्रिप्ट में लिखें और स्क्रिप्ट को निष्पादित करें। फिर ctrl-z को रोकने के लिए और आप देखेंगे कि दूसरा कमांड तब तक निष्पादित नहीं होता है जब तक कि पहला समाप्त नहीं हो जाता है। लिखना लिखना cmd; cmd; cmd;जैसा है cmd <newline> cmd <newline> ...। वैकल्पिक रूप से एक स्क्रिप्ट जिसे आप लिख सकते हैं ( cmd; cmd; cmd; ), यह स्क्रिप्ट की तरह व्यवहार करेगी, जिसके द्वारा बनाई गई उपधारा का उपयोग(
अराजकता

मैंने भी कोशिश की sleep 10। जब मैं 3 सेकंड के बाद CTRL + Z दबाता हूं और कुछ सेकंड के बाद फिर से शुरू करता हूं और देखा गया कि नींद की कमान 7 सेकंड से भी कम समय में मर गई। जो आपने कहा, उसके विपरीत है, क्योंकि कमांड नेवर को रोक दिया जाता है, यह सिर्फ पृष्ठभूमि में चलता है।
एडवर्ड टॉर्वाल्ड्स

@edwardtorvalds मैंने यह भी देखा ... समझ में नहीं आता है। मैंने कमांड को straced किया sleepऔर पाया कि सिस्टम कॉल का उपयोग किया जाता है nanosleep()। यह nanosleepसिस्टमकॉल का एक परिभाषित व्यवहार है। restart_syscall()एक समय तर्क के साथ बाधित सिस्टम कॉल को पुनरारंभ करता है जो कि पहले से ही समाप्त हो चुके समय के लिए खाते में समायोजित किया जाता है (उस समय सहित जहां प्रक्रिया एक संकेत द्वारा रोक दी गई थी)। उस मैनपेज को पढ़ें: man7.org/linux/man-pages/man2/restart_syscall.2.html
chaos

@Chaos उत्तर (उन्हें शामिल करने के लिए स्वतंत्र महसूस करें) को पूरा करने के लिए कई नोट: जब कोई ctrl-Z करता है, तो काम निलंबित ("बंद") होता है, इसलिए यह इस समय नहीं चल रहा है, आप इसे जारी रखने का फैसला करने के लिए इंतजार कर रहे हैं अग्रभूमि में (पूर्व:) fg %1या पृष्ठभूमि (उदा:) bg %1। (यदि नौकरियां केवल 1 नंबर देती हैं, यानी केवल 1 निलंबित प्रक्रिया, जैसा कि छूट की अराजकता में दिखाया गया है: केवल [1]+ stopped sleep 10, आप %nभाग को छोड़ सकते हैं । यदि कई पृष्ठभूमि प्रक्रियाएं (चल रही हैं या बंद हो गई हैं), तो आपको उस व्यक्ति को नामित करना होगा जिसे आप चाहते हैं। के साथ: %n(पूर्व: fg %2 अग्रभूमि में% 2 को फिर से शुरू करने के लिए))
ओलिवियर दुलक

6

यदि आप स्क्रिप्ट के अंदर ही रहते हुए स्क्रिप्ट को रोकना चाहते हैं तो आप नींद के बजाय रीड का उपयोग कर सकते हैं।

आप उपयोग कर सकते हैं

read -t
read -nस्क्रिप्ट जारी रखने के लिए एक वर्ण को पढ़ने के लिए एक समय-सीमा निर्धारित करना (प्रभावी रूप से बस किसी भी कुंजी को दबाएं)

जैसा कि आपने कोई कोड प्रदान नहीं किया है, नीचे इसका एक उदाहरण है कि इसका उपयोग कैसे किया जा सकता है।
यदि q दबाया जाता है, तो read -n1स्क्रिप्ट को जारी रखने से रोकता है जब तक कि एक कुंजी दबाया न जाए।
जब एक कुंजी दबाया जाता है तो चेक रीसेट हो जाता है और स्क्रिप्ट लूप में सामान्य रूप से जारी रहती है।

while [[ true ]]; do
    read -t2 -n1 check
    if [[ $check == "q" ]];then
        echo "pressed"
        read -n1
        check=""
    else
        echo "not pressed"
    fi
echo "Doing Something"
done

आप स्क्रीन आउटपुट को गड़बड़ाने से रोकने stty -echoके लिए अनुभाग की शुरुआत और stty echoअंत में भी जोड़ सकते हैं


@ बाइक चलाने वाले मुझे नहीं लगता कि ऑप को परवाह है कि क्या पढ़ा गया है, वे बस स्क्रिप्ट को रोकना और फिर से शुरू करना चाहते हैं, आपको टर्मिनल सेटिंग्स को बचाने के साथ क्या मतलब है, मैं केवल एक बदल रहा हूं ताकि थोड़ा ओवरकिल लगता है।

1
@mikeserv आह ठीक है, मैं अभी मान रहा था कि सभी स्टड उपयोगकर्ता से आ रहे हैं।

1

साथ ddआप मज़बूती से किसी फ़ाइल से कोई एकल बाइट पढ़ सकते हैं। साथ sttyआप एक सेट कर सकते हैं minएक टर्मिनल पढ़ा है और एक अर्हता प्राप्त करने के बाइट की संख्या timeएक दूसरे का दसवां में बाहर। उन दोनों को मिलाएं और आप sleepपूरी तरह से बिना कर सकते हैं , मुझे लगता है, और बस टर्मिनल के रीडआउट को आपके लिए काम करने दें:

s=$(stty -g </dev/tty)
(while stty raw -echo isig time 20 min 0;test -z "$(
dd bs=1 count=1 2>/dev/null; stty "$s")" || (exec sh)
do echo "$SECONDS:" do your stuff here maybe                             
   echo  no sleep necessary, I think                                                          
   [ "$((i+=1))" -gt 10 ] && exit                                                             
done       
) </dev/tty

यह एक छोटा सा उदाहरण whileपाश है जिसे मैंने आपके लिए आज़माया है। हर दो सेकंड में ddइसके पढ़े हुए प्रयास पर कई बार stdin- से अनुप्रेषित /dev/tty- और whileलूप लूप। क्योंकि आप एक कुंजी दबाते हैं, तो उस समय-आउट dd नहीं होता है - जिस स्थिति में एक इंटरेक्टिव शेल है।

यहाँ एक परीक्षण रन है - प्रत्येक पंक्ति के शीर्ष पर छपी संख्याएँ शेल चर का मान है $SECONDS:

273315: do your stuff here maybe
no sleep necessary, I think
273317: do your stuff here maybe
no sleep necessary, I think
273319: do your stuff here maybe
no sleep necessary, I think
273321: do your stuff here maybe
no sleep necessary, I think
sh-4.3$ : if you press a key you get an interactive shell
sh-4.3$ : this example loop quits after ten iterations
sh-4.3$ : or if this shell exits with a non-zero exit status
sh-4.3$ : and speaking of which, to do so you just...
sh-4.3$ exit
exit
273385: do your stuff here maybe
no sleep necessary, I think
273387: do your stuff here maybe
no sleep necessary, I think
273389: do your stuff here maybe
no sleep necessary, I think
273391: do your stuff here maybe
no sleep necessary, I think
273393: do your stuff here maybe
no sleep necessary, I think
273395: do your stuff here maybe
no sleep necessary, I think
273397: do your stuff here maybe
no sleep necessary, I think

क्या आपको stty saneस्टेंट सेटिंग बदलने के बाद उपयोग नहीं करना चाहिए , मैं गलत हो सकता हूं लेकिन ऐसा नहीं लगता कि आप उन्हें कहीं भी रीसेट कर सकते हैं?

@ जैडर - नहीं, मैं स्क्रिप्ट के शीर्ष पर टर्मिनल की स्थिति को बचाता हूं s=$(stty -g </dev/tty)। कॉल करने के तुरंत बाद ddमैं फिर से इसे बहाल करता हूं stty "$s"। टर्मिनल राज्य उपधाराओं के बारे में परवाह नहीं करता है और इसलिए वे सेटिंग्स पैरेंट शेल की परवाह किए बिना चिपक जाती हैं। stty saneयह जरूरी नहीं है कि आप क्या करना चाहते हैं - राज्य को उस तरह से बहाल करना बेहतर है जैसा आपने पाया था saneकि राज्य उस बिंदु पर था । अगर मैं इसे बहाल नहीं कर रहा था, तो वे echoसभी जगह पर होंगे। यह पता लगाना कि आंशिक रूप से मैं इतनी देरी से क्यों आया हूं - जब मैंने परीक्षण शुरू किया तो आपका जवाब यहां नहीं था।
मोकेसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.