नौकरी और प्रक्रिया आईडी को प्रिंट किए बिना पृष्ठभूमि में बैश कमांड चलाना


83

बैश में पृष्ठभूमि में एक प्रक्रिया को चलाने के लिए काफी आसान है।

$ echo "Hello I'm a background task" &
[1] 2076
Hello I'm a background task
[1]+  Done                    echo "Hello I'm a background task"

हालाँकि आउटपुट वर्बोज़ है। पहली पंक्ति में बैकग्राउंड टास्क के जॉब आईडी और प्रोसेस आईडी को प्रिंट किया जाता है, फिर हमारे पास कमांड का आउटपुट होता है, अंत में हमारे पास जॉब आईडी, उसकी स्थिति और कमांड होता है, जो जॉब को ट्रिगर करता है।

क्या बैकग्राउंड टास्क चलाने के आउटपुट को दबाने का एक तरीका है कि आउटपुट बिल्कुल वैसा ही दिखे जैसा कि अंत में एम्परसेंड के बिना होगा? अर्थात:

$ echo "Hello I'm a background task" &
Hello I'm a background task

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


मुझे लगता है कि आपको बैश-पूर्ण स्क्रिप्ट के अंदर कुछ भी करने के लिए 2> / देव / अशक्त जोड़ना चाहिए
सेह

जवाबों:


98

पूरा होने से संबंधित नहीं है, लेकिन आप कॉल को एक सब-कॉल में डालकर उस आउटपुट को दबा सकते हैं:

(echo "Hello I'm a background task" &)

3
धन्यवाद, यह निश्चित रूप से काम करता है। दुर्भाग्यवश, जब एक स्क्रिप्ट को बैश-पूरा होने वाले फ़ंक्शन से इस तरह से चलाया जाता है, तो यह प्रतीत होता है कि बैश का इंतजार तब तक होता है जब तक कि पूरा होने से पहले सबप्रोसेस पूरा न हो जाए। यह दुर्भाग्यपूर्ण है क्योंकि इसका मतलब है कि पृष्ठभूमि के श्रमिकों को बैश-पूरा होने से ट्रिगर करना संभव नहीं है।
एलेक्स स्परलिंग

13
अगर आप waitबैकग्राउंड जॉब खत्म करना चाहते हैं तो आप इसका इस्तेमाल नहीं कर सकते ।
इस्कॉलेक

13

@ शेल्टर के उत्तर का निर्माण, यह मेरे लिए काम कर रहा है:

tyler@Tyler-Linux:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1;
Hello I'm a background task
tyler@Tyler-Linux:~$

मुझे इसके पीछे के तर्क का पता नहीं है, लेकिन मुझे एक पुरानी पोस्ट से याद आया जो कि डिस को प्रोसेस आईडी को आउटपुट करने से रोकता है।


@ टायज़ॉइड मैंने आपके समाधान को बैश शेल (v 4.2.37) में आज़माया और उसके दिलचस्प परिणाम आए। 1. मैं ;अंत में जोड़कर एक ही परिणाम प्राप्त किया। (बिना सोए) । 2. लेकिन ध्यान दिया कि जब मैंने echo STDERR 2>&1"अगली" लाइन में जोड़ा , तब [1]+ Done ...बात सामने आई! । 3. मेरा समाधान (जैसा कि मैंने अब नोट किया है) काम करता है kshऔर echo STDERR 2>&1केवल आउटपुट STDERR का उत्पादन करता है। खैर, हम दोनों के लिए जीना और सीखना। आप सभी को शुभकामनायें।
शेल्टर

12

बैश के कुछ नए संस्करणों में और ksh93 में आप इसे सब-शेल या प्रोसेस ग्रुप (यानी { ... }) के साथ घेर सकते हैं ।

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $

5
जब मैं घुंघराले ब्रेसिज़ का उपयोग करता हूं, तो आउटपुट की अंतिम पंक्ति अभी भी दिखाती है (मुझे यकीन नहीं है कि आप इसे क्यों नहीं देखते हैं)।
एलेक्स स्पर्लिंग

मैंने इसे बिल्कुल कॉपी किया है, लेकिन यह मेरे लिए काम नहीं करता है, यह अभी भी आउटपुट दिखाता है जैसा कि @AlexSpurling कहते हैं। हो सकता है कि मैं कुछ गलत कर रहा हूं क्योंकि अन्य लोगों ने इसे गलत ठहराया है, लेकिन मुझे डर है कि मुझे इसे देना होगा -1।
मार्क

1
@ मर्क: मैंने अभी इसके साथ कुछ त्वरित परीक्षण किए हैं और मुझे समस्या यह है कि मैं ksh93+अपने प्राइमररी शेल के रूप में उपयोग करना जारी रखता हूं। यह कोड ksh में वादे के अनुसार काम करता है। लेकिन जैसे ही ओपी को टैग किया जाता है, bashमैं आपकी DV को समझता हूं। @ Tyzoid के उत्तर पर बैश परीक्षण के परिणाम देखें। आप सभी को शुभकामनायें!
शेल्टर

चूंकि आपने यह स्पष्ट कर दिया है कि यह bash में काम नहीं करता है इसलिए मैं -1 को हटा दूंगा।
मार्क

1
मेरे लिए यह एक बश फ़ंक्शन में बहुत अच्छा काम करता है, यह भी प्रक्रिया के लिए इंतजार किया जा सकता है wait $!जिसके साथ स्वीकार्य उत्तर के लिए मामला नहीं लगता है।
जोनाटन öström

6

उपरोक्त उत्तर पर निर्माण करना, यदि आपको कमांडर को कमांड से आने की अनुमति देने की आवश्यकता है:

f() { echo "Hello I'm a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null

पुनर्निर्देश का सुंदर उपयोग। फिर भी, आपको disownकुछ परिस्थितियों में आवश्यकता होगी
टॉम हेल

6

इस उत्तर के आधार पर , मैं अधिक संक्षिप्त और सही के साथ आया:

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date

उत्तम! और अन्य सामान के लिए पुन: प्रयोज्य
user230910

5

प्रयत्न:

user@host:~$ read < <( echo "Hello I'm a background task" & echo $! )
user@host:~$ echo $REPLY
28677

और आपने आउटपुट और PID दोनों को छिपाया है । ध्यान दें कि आप अभी भी $ REPLY से PID को पुनः प्राप्त कर सकते हैं


1
यह पूर्ण है! धन्यवाद
अदम

4

एक पुरानी पोस्ट की प्रतिक्रिया के लिए क्षमा करें, लेकिन मुझे लगता है कि यह दूसरों के लिए उपयोगी है, और यह Google पर पहली प्रतिक्रिया है।

मैं इस पद्धति (उपधारा) के साथ एक मुद्दा बना रहा था और 'प्रतीक्षा' का उपयोग कर रहा था। हालाँकि, जब मैं इसे एक फंक्शन के अंदर चला रहा था, मैं यह करने में सक्षम था:

function a {
    echo "I'm background task $1"
    sleep 5
}

function b {
    for i in {1..10}; do
        a $i &
    done
    wait
} 2>/dev/null

और जब मैं इसे चलाता हूं:

$ b
I'm background task 1
I'm background task 3
I'm background task 2
I'm background task 4
I'm background task 6
I'm background task 7
I'm background task 5
I'm background task 9
I'm background task 8
I'm background task 10

और मुझे वापस आने से पहले 5 सेकंड की देरी हो रही है।


1

उपधारा समाधान काम करता है, लेकिन मैं पृष्ठभूमि की नौकरियों पर प्रतीक्षा करने में सक्षम होना चाहता था (और अंत में "पूर्ण" संदेश नहीं है)। $!वर्तमान इंटरेक्टिव शेल में एक सबशेल "वेटेबल" नहीं है। मेरे लिए काम करने वाला एकमात्र समाधान मेरे स्वयं के प्रतीक्षा फ़ंक्शन का उपयोग करना था, जो बहुत सरल है:

myWait() {
  while true; do
    sleep 1; STOP=1
    for p in $*; do
      ps -p $p >/dev/null && STOP=0 && break
    done
    ((STOP==1)) && return 0
  done
}

i=0
((i++)); p[$i]=$(do_whatever1 & echo $!)
((i++)); p[$i]=$(do_whatever2 & echo $!)
..
myWait ${p[*]}

काफी आसान।

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