अधिकतम प्रक्रियाओं के साथ बैश स्क्रिप्ट को समानांतर करें


86

आइए हम कहते हैं कि मेरे पास बैश में एक लूप है:

for foo in `some-command`
do
   do-something $foo
done

do-somethingसीपीयू बाध्य है और मेरे पास एक अच्छा चमकदार 4 कोर प्रोसेसर है। मैं do-somethingएक बार में 4 तक दौड़ना चाहूंगा ।

अनुभवहीन दृष्टिकोण लगता है:

for foo in `some-command`
do
   do-something $foo &
done

यह एक बार में सभी को चलाएगा do-something, लेकिन एक जोड़ी डाउनसाइड हैं, मुख्य रूप से ऐसा करना कुछ महत्वपूर्ण I / O भी हो सकता है जो एक बार में सभी प्रदर्शन थोड़ा धीमा कर सकते हैं। दूसरी समस्या यह है कि यह कोड ब्लॉक तुरंत वापस आ जाता है, इसलिए अन्य काम पूरा करने का कोई तरीका नहीं है do-something

आप इस लूप को कैसे लिखेंगे ताकि do-somethingएक ही बार में हमेशा X चल रहे हों?


2
एक सिडेनोड के रूप में, मैंने आदिम के लिए बैश में मेक-जे विकल्प जोड़ने का सपना देखा है। यह हमेशा काम नहीं करेगा, लेकिन कुछ सरल मामलों के लिए जहां आप जानते हैं कि लूप का शरीर प्रत्येक पुनरावृत्ति के लिए कुछ अनोखा करने जा रहा है, यह सिर्फ "for -j 4 ..." कहने के लिए बहुत साफ होगा।
खोलना

1
करने के लिए परस्पर-संदर्भ stackoverflow.com/questions/1537956/... एक बैश समाधान जो mitigates प्रदर्शन की समस्याओं और उप प्रक्रियाओं के समूहों के लिए अनुमति देता है के लिए, अलग रखा।
paxdiablo

1
मैं अपने समाधान stackoverflow.com/a/28965927/340581
टटलू

जवाबों:


62

जो आप xargs करना चाहते हैं उसके आधार पर भी मदद कर सकते हैं (यहाँ: pdf2ps के साथ दस्तावेज़ परिवर्तित करना):

cpus=$( ls -d /sys/devices/system/cpu/cpu[[:digit:]]* | wc -w )

find . -name \*.pdf | xargs --max-args=1 --max-procs=$cpus  pdf2ps

डॉक्स से:

--max-procs=max-procs
-P max-procs
       Run up to max-procs processes at a time; the default is 1.
       If max-procs is 0, xargs will run as many processes as  possible  at  a
       time.  Use the -n option with -P; otherwise chances are that only one
       exec will be done.

9
यह विधि, मेरी राय में, सबसे सुरुचिपूर्ण समाधान है। सिवाय इसके, जब से मैं पागल हूं, मैं हमेशा उपयोग करना पसंद करता हूं find [...] -print0और xargs -0
एम्फेटामैचिन

7
cpus=$(getconf _NPROCESSORS_ONLN)
mr.spuratic

1
मैनुअल से, क्यों --max-procs=0संभव के रूप में कई प्रक्रियाओं को प्राप्त करने के लिए उपयोग नहीं किया जाता है?
सब कुछ

@EverythingRightPlace, प्रश्न स्पष्ट रूप से उपलब्ध प्रोसेसर की तुलना में अधिक प्रक्रियाओं के लिए नहीं पूछता है। --max-procs=0प्रश्नकर्ता के प्रयास की तरह अधिक है (तर्कों के रूप में कई प्रक्रियाओं को शुरू करें)।
टोबे स्पाइट

39

GNU समानांतर के साथ http://www.gnu.org/software/parallel/ आप लिख सकते हैं:

some-command | parallel do-something

जीएनयू समानांतर भी दूरस्थ कंप्यूटर पर रोजगार चलाने का समर्थन करता है। यह दूरस्थ कंप्यूटर पर एक प्रति CPU कोर चलाएगा - भले ही उनके पास कोर की अलग-अलग संख्या हो:

some-command | parallel -S server1,server2 do-something

एक और अधिक उन्नत उदाहरण: यहाँ हम उन फाइलों की सूची देते हैं जिन्हें हम चाहते हैं कि my_script चालू हो। फाइलें एक्सटेंशन (शायद .jpeg) में हैं। हम my_script के आउटपुट को बेसेंमे.आउट (उदाहरण के लिए foo.jpeg -> foo.out) में फाइलों के बगल में रखना चाहते हैं। हम प्रत्येक कंप्यूटर के लिए एक बार my_script चलाना चाहते हैं और हम इसे स्थानीय कंप्यूटर पर भी चलाना चाहते हैं। दूरस्थ कंप्यूटरों के लिए हम चाहते हैं कि फ़ाइल को दिए गए कंप्यूटर में संसाधित किया जाए। जब my_script खत्म हो जाती है, तो हम चाहते हैं कि foo.out वापस ट्रांसफर हो जाए और हम दूरस्थ कंप्यूटर से foo.jpeg और foo.out चाहते हैं:

cat list_of_files | \
parallel --trc {.}.out -S server1,server2,: \
"my_script {} > {.}.out"

जीएनयू समानांतर यह सुनिश्चित करता है कि प्रत्येक नौकरी से आउटपुट मिश्रण नहीं करता है, इसलिए आप आउटपुट को किसी अन्य प्रोग्राम के लिए इनपुट के रूप में उपयोग कर सकते हैं:

some-command | parallel do-something | postprocess

अधिक उदाहरणों के लिए वीडियो देखें: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


1
ध्यान दें कि findफ़ाइल सूची बनाने के लिए कमांड का उपयोग करते समय यह वास्तव में उपयोगी है , क्योंकि यह न केवल उस समस्या को रोकता है जब फ़ाइल नाम के अंदर एक स्थान होता है, for i in ...; doलेकिन यह भी पता चलता है कि find -name \*.extension1 -or -name \*.extension2कौन सा GNU समानांतर के {}} बहुत अच्छी तरह से संभाल सकता है।
सिंह इयोजन

प्लस 1 हालांकि cat, ज़ाहिर है, बेकार है।
4

@tripleee Re: बिल्ली का बेकार उपयोग। देखें oletange.blogspot.dk/2013/10/useless-use-of-cat.html
ओले Tange

ओह यह आप हैं! संयोग से, क्या आप उस ब्लॉग के लिंक को अपडेट कर सकते हैं? Partmaps.org स्थान अफसोसजनक रूप से मृत है, लेकिन इकी पुनर्निर्देशक को काम करना जारी रखना चाहिए।
ट्रिपल

22
maxjobs = 4
समानांतर () {
        जबकि [$ # -gt 0]; करना
                jobcnt = (`कार्य -p`)
                अगर [$ {# jobcnt [@]} -lt $ maxjobs]; फिर
                        $ 1 & कुछ करें
                        खिसक जाना  
                अन्य
                        सो जाओ १
                फाई
        किया हुआ
        रुको
}

समानांतर arg1 arg2 "5 आर्ग्स टू थर्ड जॉब" arg4 ...

10
एहसास है कि यहां कुछ गंभीर अंडरकॉटिंग चल रही है, इसलिए किसी भी नौकरी के लिए तर्क में रिक्त स्थान की आवश्यकता होती है जो बुरी तरह से विफल हो जाएगी; इसके अलावा, यह स्क्रिप्ट आपके सीपीयू को जीवित खाएगी, जबकि कुछ नौकरियों के खत्म होने की प्रतीक्षा में अगर अधिकतम नौकरी के लिए अनुरोध किया जाता है।
प्रात:

1
यह भी ध्यान दें कि यह मानती है कि आपकी स्क्रिप्ट नौकरियों के साथ कुछ और नहीं कर रही है; यदि आप कर रहे हैं, तो यह उन लोगों को भी मैक्सकोर्स की ओर गिना जाएगा।
प्रातः

1
आप रनिंग जॉब्स को सीमित करने के लिए "जॉब्स -प्र" का उपयोग करना चाह सकते हैं।
एम्फ़ैटेमाचिन

1
बिना किसी ब्रेक के दोहराए जाने से लूप को रोकने के लिए स्लीप कमांड जोड़ा गया, जबकि यह पहले से चल रहे कुछ कमांड के खत्म होने का इंतजार करता है। अन्यथा, यह लूप अनिवार्य रूप से सीपीयू कोर में से एक को ले जाएगा। यह @ ललनाथ की चिंता को भी संबोधित करता है।
युफोरिया83

12

यहां एक वैकल्पिक समाधान जिसे .bashrc में डाला जा सकता है और इसका उपयोग हर रोज एक लाइनर के लिए किया जा सकता है:

function pwait() {
    while [ $(jobs -p | wc -l) -ge $1 ]; do
        sleep 1
    done
}

इसका उपयोग करने के लिए, सभी &को नौकरियों और एक कॉल कॉल के बाद रखा जाना चाहिए , पैरामीटर समानांतर प्रक्रियाओं की संख्या देता है:

for i in *; do
    do_something $i &
    pwait 10
done

waitके आउटपुट पर प्रतीक्षा में व्यस्त होने के बजाय इसका उपयोग करना अच्छा होगा jobs -p, लेकिन इन सभी के बजाय किसी भी दिए गए कार्य के समाप्त होने तक प्रतीक्षा करने के लिए एक स्पष्ट समाधान प्रतीत नहीं होता है।


11

एक सादे बैश के बजाय, एक मेकफिल का उपयोग करें, फिर एक साथ नौकरियों की संख्या निर्दिष्ट करें make -jXजहां एक्स को एक बार चलाने के लिए नौकरियों की संख्या है।

या आप wait(" man wait") का उपयोग कर सकते हैं : कई बच्चे प्रक्रियाओं को लॉन्च करें, कॉल करें wait- जब बच्चे प्रक्रिया समाप्त करेंगे तो यह बाहर निकल जाएगा।

maxjobs = 10

foreach line in `cat file.txt` {
 jobsrunning = 0
 while jobsrunning < maxjobs {
  do job &
  jobsrunning += 1
 }
wait
}

job ( ){
...
}

यदि आपको नौकरी के परिणाम को संग्रहीत करने की आवश्यकता है, तो उनके परिणाम को एक चर पर असाइन करें। waitआपके द्वारा जाँचने के बाद कि चर में क्या है।


1
इसके लिए धन्यवाद, भले ही कोड समाप्त नहीं हुआ है, यह मुझे एक समस्या का जवाब दे रहा है जो मुझे काम पर है।
जीरिकसन

केवल परेशानी यह है कि यदि आप अग्रभूमि स्क्रिप्ट (लूप के साथ एक) को मारते हैं, तो जो नौकरियां चल रही हैं, वे एक साथ नहीं मारे जाएंगे
गिरधारी

8

शायद लूप को फिर से लिखने के बजाय एक समानांतर उपयोगिता की कोशिश करें? मैं xjobs का बहुत बड़ा प्रशंसक हूं। मैं अपने नेटवर्क पर फ़ाइलों की बड़े पैमाने पर प्रतिलिपि बनाने के लिए हर समय xjobs का उपयोग करता हूं, आमतौर पर एक नया डेटाबेस सर्वर स्थापित करते समय। http://www.maier-komor.de/xjobs.html


7

यदि आप makeकमांड से परिचित हैं , तो अधिकांश समय आप उन कमांड की सूची को व्यक्त कर सकते हैं जिन्हें आप एएफ़ाइल के रूप में चलाना चाहते हैं। उदाहरण के लिए, यदि आपको फ़ाइलों पर $ SOME_COMMAND चलाने की आवश्यकता है *। जिनमें से प्रत्येक * .output का उत्पादन करता है, आप मेकफाइल का उपयोग कर सकते हैं

INPUT = a.input b.input
OUTPUT = $ (INPUT: .input = .output)

%।आउटपुट इनपुट
    $ (SOME_COMMAND) $ <$ @

सभी: $ (OUTPUT)

और फिर बस चलाओ

मेक -j <NUMBER>

समानांतर में अधिकांश NUMBER आदेशों पर चलने के लिए।


6

इस अधिकार को bashकरना असंभव है, लेकिन आप आसानी से एक अर्ध-सही तरीके से कर सकते हैं। bstarkसही का एक अनुमानित अनुमान दिया, लेकिन उसके दोष निम्नलिखित हैं:

  • शब्द विभाजन: आप इसके लिए कोई भी कार्य नहीं कर सकते हैं जो निम्न में से किसी भी वर्ण का उपयोग उनके तर्कों में करते हैं: रिक्त स्थान, टैब, नई सूचियाँ, सितारे, प्रश्न चिह्न। यदि आप करते हैं, तो चीजें टूट जाएंगी, संभवतः अप्रत्याशित रूप से।
  • यह आपकी स्क्रिप्ट के बाकी हिस्सों पर निर्भर करता है, ताकि किसी भी चीज की पृष्ठभूमि न हो। यदि आप करते हैं, या बाद में आप स्क्रिप्ट में कुछ जोड़ते हैं जो पृष्ठभूमि में भेजा जाता है क्योंकि आप भूल गए थे कि आपको उसके स्निपेट के कारण पृष्ठभूमि वाली नौकरियों का उपयोग करने की अनुमति नहीं थी, तो चीजें टूट जाएंगी।

एक और सन्निकटन जिसमें ये दोष नहीं हैं, निम्नलिखित है:

scheduleAll() {
    local job i=0 max=4 pids=()

    for job; do
        (( ++i % max == 0 )) && {
            wait "${pids[@]}"
            pids=()
        }

        bash -c "$job" & pids+=("$!")
    done

    wait "${pids[@]}"
}

ध्यान दें कि यह आसानी से प्रत्येक नौकरी के निकास कोड की जांच करने के लिए भी अनुकूलनीय है क्योंकि यह समाप्त हो जाता है ताकि आप उपयोगकर्ता को चेतावनी दे सकें कि नौकरी विफल हो जाती है या scheduleAllविफल रही नौकरियों की मात्रा के अनुसार एक निकास कोड सेट करते हैं, या कुछ और।

इस कोड के साथ समस्या यह है कि:

  • यह एक समय में चार (इस मामले में) नौकरियों का शेड्यूल करता है और फिर चारों के खत्म होने का इंतजार करता है। कुछ अन्य की तुलना में जल्द ही किया जा सकता है जो अगले बैच के सबसे लंबे समय तक किए जाने तक प्रतीक्षा करने के लिए चार नौकरियों के अगले बैच का कारण होगा।

एक समाधान जो इस अंतिम मुद्दे का ध्यान रखता है, उसे यह देखने के लिए उपयोग करना होगा kill -0कि क्या कोई भी प्रक्रिया इसके बजाय गायब हो गई है waitऔर अगले काम को शेड्यूल करें। हालाँकि, यह एक छोटी सी नई समस्या का परिचय देता है: आपके पास एक नौकरी समाप्त होने और kill -0इसे समाप्त होने की जाँच के बीच एक दौड़ की स्थिति है । यदि नौकरी समाप्त हो गई और एक ही समय में आपके सिस्टम पर एक और प्रक्रिया शुरू हो जाती है, तो एक यादृच्छिक पीआईडी ​​लेना जो कि उस नौकरी से होता है जो समाप्त हो गया है, kill -0आपकी नौकरी समाप्त होने पर ध्यान नहीं देगा और चीजें फिर से टूट जाएंगी।

एक सही समाधान संभव नहीं है bash


3

समारोह के लिए बैश:

parallel ()
{
    awk "BEGIN{print \"all: ALL_TARGETS\\n\"}{print \"TARGET_\"NR\":\\n\\t@-\"\$0\"\\n\"}END{printf \"ALL_TARGETS:\";for(i=1;i<=NR;i++){printf \" TARGET_%d\",i};print\"\\n\"}" | make $@ -f - all
}

का उपयोग करते हुए:

cat my_commands | parallel -j 4

का उपयोग make -jचतुर है, लेकिन कोई स्पष्टीकरण नहीं है और केवल लिखने वाले ऑक कोड की बूँद के साथ, मैं अपवित्र होने से बचता हूं।
ट्रिपल जूल

2

मैं जिस परियोजना पर काम करता हूं वह समानांतर शेल (ksh वास्तव में) प्रक्रियाओं को नियंत्रित करने के लिए प्रतीक्षा कमांड का उपयोग करती है। आधुनिक ओएस पर, आईओ के बारे में अपनी चिंताओं को दूर करने के लिए, यह संभव है कि समानांतर निष्पादन वास्तव में दक्षता बढ़ाएगा। यदि सभी प्रक्रियाएं डिस्क पर समान ब्लॉक पढ़ रही हैं, तो केवल पहली प्रक्रिया में भौतिक हार्डवेयर को हिट करना होगा। अन्य प्रक्रियाएं अक्सर मेमोरी में ओएस के डिस्क कैश से ब्लॉक को पुनः प्राप्त करने में सक्षम होंगी। जाहिर है, मेमोरी से पढ़ना डिस्क से पढ़ने की तुलना में तेज परिमाण के कई आदेश हैं। इसके अलावा, लाभ को कोडिंग परिवर्तनों की आवश्यकता नहीं है।


1

यह अधिकांश उद्देश्यों के लिए पर्याप्त हो सकता है, लेकिन इष्टतम नहीं है।

#!/bin/bash

n=0
maxjobs=10

for i in *.m4a ; do
    # ( DO SOMETHING ) &

    # limit jobs
    if (( $(($((++n)) % $maxjobs)) == 0 )) ; then
        wait # wait until all have finished (not optimal, but most times good enough)
        echo $n wait
    fi
done

1

इस प्रकार मैं इस मुद्दे को बश लिपि में हल करने में कामयाब रहा:

 #! /bin/bash

 MAX_JOBS=32

 FILE_LIST=($(cat ${1}))

 echo Length ${#FILE_LIST[@]}

 for ((INDEX=0; INDEX < ${#FILE_LIST[@]}; INDEX=$((${INDEX}+${MAX_JOBS})) ));
 do
     JOBS_RUNNING=0
     while ((JOBS_RUNNING < MAX_JOBS))
     do
         I=$((${INDEX}+${JOBS_RUNNING}))
         FILE=${FILE_LIST[${I}]}
         if [ "$FILE" != "" ];then
             echo $JOBS_RUNNING $FILE
             ./M22Checker ${FILE} &
         else
             echo $JOBS_RUNNING NULL &
         fi
         JOBS_RUNNING=$((JOBS_RUNNING+1))
     done
     wait
 done

1

यहां पार्टी के लिए वास्तव में देर हो चुकी है, लेकिन यहां एक और समाधान है।

बहुत सारे समाधान आदेशों में रिक्त स्थान / विशेष पात्रों को नहीं संभालते हैं, हर समय एन नौकरियों को चालू नहीं रखते हैं, व्यस्त छोरों में सीपीयू खाते हैं, या बाहरी निर्भरता (जैसे जीएनयू parallel) पर भरोसा करते हैं ।

मृत / ज़ोंबी प्रक्रिया से निपटने के लिए प्रेरणा के साथ , यहाँ एक शुद्ध बैश समाधान है:

function run_parallel_jobs {
    local concurrent_max=$1
    local callback=$2
    local cmds=("${@:3}")
    local jobs=( )

    while [[ "${#cmds[@]}" -gt 0 ]] || [[ "${#jobs[@]}" -gt 0 ]]; do
        while [[ "${#jobs[@]}" -lt $concurrent_max ]] && [[ "${#cmds[@]}" -gt 0 ]]; do
            local cmd="${cmds[0]}"
            cmds=("${cmds[@]:1}")

            bash -c "$cmd" &
            jobs+=($!)
        done

        local job="${jobs[0]}"
        jobs=("${jobs[@]:1}")

        local state="$(ps -p $job -o state= 2>/dev/null)"

        if [[ "$state" == "D" ]] || [[ "$state" == "Z" ]]; then
            $callback $job
        else
            wait $job
            $callback $job $?
        fi
    done
}

और नमूना उपयोग:

function job_done {
    if [[ $# -lt 2 ]]; then
        echo "PID $1 died unexpectedly"
    else
        echo "PID $1 exited $2"
    fi
}

cmds=( \
    "echo 1; sleep 1; exit 1" \
    "echo 2; sleep 2; exit 2" \
    "echo 3; sleep 3; exit 3" \
    "echo 4; sleep 4; exit 4" \
    "echo 5; sleep 5; exit 5" \
)

# cpus="$(getconf _NPROCESSORS_ONLN)"
cpus=3
run_parallel_jobs $cpus "job_done" "${cmds[@]}"

उत्पादन:

1
2
3
PID 56712 exited 1
4
PID 56713 exited 2
5
PID 56714 exited 3
PID 56720 exited 4
PID 56724 exited 5

प्रति-प्रक्रिया आउटपुट हैंडलिंग के $$लिए फ़ाइल में लॉग इन करने के लिए इस्तेमाल किया जा सकता है, उदाहरण के लिए:

function job_done {
    cat "$1.log"
}

cmds=( \
    "echo 1 \$\$ >\$\$.log" \
    "echo 2 \$\$ >\$\$.log" \
)

run_parallel_jobs 2 "job_done" "${cmds[@]}"

आउटपुट:

1 56871
2 56872

0

आप लूप के लिए एक साधारण नेस्टेड का उपयोग कर सकते हैं (नीचे एन और एम के लिए उपयुक्त पूर्णांक चुनें):

for i in {1..N}; do
  (for j in {1..M}; do do_something; done & );
done

यह do_something N * M को M राउंड में निष्पादित करेगा, प्रत्येक राउंड N समानांतर में N जॉब निष्पादित करेगा। आपके पास जितने सीपीयू हैं, आप उसके बराबर एन बना सकते हैं।


0

मेरा समाधान हमेशा दी गई प्रक्रियाओं की संख्या को बनाए रखना है, त्रुटियों पर नज़र रखना है और सर्वव्यापी / ज़ोंबी प्रक्रियाओं को संभालना है:

function log {
    echo "$1"
}

# Take a list of commands to run, runs them sequentially with numberOfProcesses commands simultaneously runs
# Returns the number of non zero exit codes from commands
function ParallelExec {
    local numberOfProcesses="${1}" # Number of simultaneous commands to run
    local commandsArg="${2}" # Semi-colon separated list of commands

    local pid
    local runningPids=0
    local counter=0
    local commandsArray
    local pidsArray
    local newPidsArray
    local retval
    local retvalAll=0
    local pidState
    local commandsArrayPid

    IFS=';' read -r -a commandsArray <<< "$commandsArg"

    log "Runnning ${#commandsArray[@]} commands in $numberOfProcesses simultaneous processes."

    while [ $counter -lt "${#commandsArray[@]}" ] || [ ${#pidsArray[@]} -gt 0 ]; do

        while [ $counter -lt "${#commandsArray[@]}" ] && [ ${#pidsArray[@]} -lt $numberOfProcesses ]; do
            log "Running command [${commandsArray[$counter]}]."
            eval "${commandsArray[$counter]}" &
            pid=$!
            pidsArray+=($pid)
            commandsArrayPid[$pid]="${commandsArray[$counter]}"
            counter=$((counter+1))
        done


        newPidsArray=()
        for pid in "${pidsArray[@]}"; do
            # Handle uninterruptible sleep state or zombies by ommiting them from running process array (How to kill that is already dead ? :)
            if kill -0 $pid > /dev/null 2>&1; then
                pidState=$(ps -p$pid -o state= 2 > /dev/null)
                if [ "$pidState" != "D" ] && [ "$pidState" != "Z" ]; then
                    newPidsArray+=($pid)
                fi
            else
                # pid is dead, get it's exit code from wait command
                wait $pid
                retval=$?
                if [ $retval -ne 0 ]; then
                    log "Command [${commandsArrayPid[$pid]}] failed with exit code [$retval]."
                    retvalAll=$((retvalAll+1))
                fi
            fi
        done
        pidsArray=("${newPidsArray[@]}")

        # Add a trivial sleep time so bash won't eat all CPU
        sleep .05
    done

    return $retvalAll
}

उपयोग:

cmds="du -csh /var;du -csh /tmp;sleep 3;du -csh /root;sleep 10; du -csh /home"

# Execute 2 processes at a time
ParallelExec 2 "$cmds"

# Execute 4 processes at a time
ParallelExec 4 "$cmds"

-1

$ DOMAINS = "foo में some-command डू के लिए कमांड्स में कुछ डोमेन की सूची"

eval `some-command for $DOMAINS` &

    job[$i]=$!

    i=$(( i + 1))

किया हुआ

Ndomains =echo $DOMAINS |wc -w

$ i में (seq 1 1 $ Ndomains) प्रतिध्वनि "$ {job [$ i]} के लिए प्रतीक्षा करें" $ {job [$ i]} "

इस अवधारणा में समानांतर के लिए काम करेंगे। महत्वपूर्ण बात यह है कि eval की अंतिम पंक्ति 'और' है जो कमांड्स को पृष्ठभूमि में रखेगी।

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