कॉलिंग कार्य xargs के साथ


168

मैं समानांतर में अधिक जटिल फ़ंक्शन को कॉल करने के लिए xargs का उपयोग करने का प्रयास कर रहा हूं।

#!/bin/bash
echo_var(){
    echo $1
    return 0
}
seq -f "n%04g" 1 100 |xargs -n 1 -P 10 -i echo_var {} 
exit 0

यह त्रुटि देता है

xargs: echo_var: No such file or directory

इसे पूरा करने के लिए मैं xargs का उपयोग कैसे कर सकता हूं, इस पर कोई विचार या किसी अन्य समाधान का स्वागत किया जाएगा।


2
खतरा, user1148366, खतरे! समानांतर प्रोग्रामिंग के लिए बैश का उपयोग न करें- आप बहुत सारी समस्याओं में भाग जाएंगे। C / C ++ और pthreads, या Java थ्रेड्स या किसी भी चीज़ का उपयोग करें जो आपके द्वारा किए जा रहे काम के बारे में लंबा और कठिन लगता है, क्योंकि समानांतर प्रोग्रामिंग सही होने के लिए बहुत अधिक विचार करती है।
डेविड सूटर

27
@DavidSouther यदि कार्य स्वतंत्र हैं, जैसे कि इन सभी चित्र फ़ाइलों को पीएनजी में परिवर्तित करें, तो चिंता न करें। यह तब होता है जब आपके पास सिंक्रनाइज़ेशन (सभी समाप्त होने की प्रतीक्षा से परे) और संचार होता है कि यह गड़बड़ हो जाता है।
ctrl-alt-delor

@DavidSouther - मैं लंबे समय से जावा देव हूं और मैं देर से काम कर रहा हूं। और मैं लोगों को बताना जारी रखता हूं: दोस्तों ने दोस्तों को बैश स्क्रिप्ट लिखने नहीं दिया। और फिर भी, मैं खुद को इस पद / समाधान को देख रहा हूं क्योंकि (उदास चेहरा :() मैं बैश में समानांतर प्रसंस्करण में लगा हुआ हूं। मैं आसानी से इसे groovy / java में कर सकता हूं। बुरा!
ईसाई बोंगोइरोनो

जवाबों:


172

समारोह का निर्यात इसे करना चाहिए (अप्राप्त):

export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}

आप printfबाहरी के बजाय बिलिन का उपयोग कर सकते हैं seq:

printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}

इसके अलावा, किसी भी त्रुटि मान का उपयोग करने return 0और exit 0उस तरह का उपयोग करना जो कि कमांड से पहले हो सकता है। इसके अलावा, अगर कोई त्रुटि नहीं है, तो यह डिफ़ॉल्ट है और इस प्रकार कुछ हद तक बेमानी है।

@ एफ़ोबिक में उल्लेख है कि बैश कमांड को सरल बनाया जा सकता है

bash -c 'echo_var "{}"'

{}सीधे उसके अंदर चल रहा है। लेकिन यह @Sasha द्वारा इंगित के रूप में कमांड इंजेक्शन के लिए असुरक्षित है

यहाँ एक उदाहरण है कि आपको एम्बेडेड प्रारूप का उपयोग क्यों नहीं करना चाहिए :

$ echo '$(date)' | xargs -I {} bash -c 'echo_var "{}"'
Sun Aug 18 11:56:45 CDT 2019

क्यों नहीं का एक और उदाहरण :

echo '\"; date\"' | xargs -I {} bash -c 'echo_var "{}"'

सुरक्षित प्रारूप का उपयोग करके यह आउटपुट है :

$ echo '$(date)' | xargs -I {} bash -c 'echo_var "$@"' _ {}
$(date)

यह इंजेक्शन से बचने के लिए पैरामीटर वाले SQL प्रश्नों का उपयोग करने के लिए तुलनीय है

मैं dateएक कमांड प्रतिस्थापन में उपयोग कर रहा हूं या rmसाशा की टिप्पणी में इस्तेमाल किए गए कमांड के बजाय यहां से बच गए उद्धरणों के बाद से यह गैर-विनाशकारी है।


14
थोड़ी और चर्चा: xargs नाम की प्रक्रिया का एक नया उदाहरण निष्पादित करता है। इस स्थिति में, आप नाम प्रदान करते हैं echo_var, जो इस स्क्रिप्ट में एक फ़ंक्शन है, न कि आपके PATH में एक प्रक्रिया (प्रोग्राम)। डेनिस का समाधान क्या करता है, बच्चे की बैश प्रक्रियाओं का उपयोग करने के लिए फ़ंक्शन का निर्यात करता है, फिर उपप्रोसेस के लिए कांटे और वहां निष्पादित करता है।
डेविड सॉथर

7
क्या महत्व है _और \, उनके बिना यह मेरे लिए काम नहीं कर रहा था
हाशबोर्न

9
@Hashbrown: अंडरस्कोर ( _) के लिए एक जगह धारक प्रदान करता है argv[0]( $0) और लगभग कुछ भी वहाँ इस्तेमाल किया जा सकता। मुझे लगता है कि मैंने क्लॉज़ को \;समाप्त करने में इसके उपयोग के कारण बैकस्लैश-सेमीकोलन ( ) को जोड़ा , लेकिन यह मेरे बिना यहां काम करता है। वास्तव में, यदि फ़ंक्शन इसके बजाय उपयोग करना था, तो यह अर्धविराम को एक पैरामीटर के रूप में देखेगा, इसलिए इसे छोड़ दिया जाना चाहिए। -execfind$@$1
अगली सूचना तक रोक दिया गया।

4
xigs का तर्क तब से हटा दिया गया है। उपयोग -I (पूंजी i) के बजाय।
निकोलई एस

11
आप कमांड स्ट्रिंग में xargs के तर्क को bash के लिए शामिल करके इसे सरल बना सकते हैं bash -c 'echo_var "{}"'। इसलिए आपको अंत में _ {} की आवश्यकता नहीं है।
फोबिक

16

GNU पैरेलल का उपयोग इस तरह होता है:

#!/bin/bash
echo_var(){
    echo $1
    return 0
}
export -f echo_var
seq -f "n%04g" 1 100 | parallel -P 10 echo_var {} 
exit 0

यदि आप संस्करण 20170822 का उपयोग करते हैं तो आपके पास भी ऐसा नहीं है export -fजब तक कि आपने इसे चलाया हो:

. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var {} 

मुझे ओएक्सएक्स के लिए कहां से खरीदारी करनी है?
निक

nvm यह zsh में सेट किया गया है
निक

यह नीचे दिए गए eerror Ole sh: parallel_bash_environment: line 67: unexpected EOF while looking for matching '' sh: समानांतर_ bash_environment : लाइन 79: सिंटैक्स त्रुटि: फ़ाइल श का अनपेक्षित अंत: parallel_bash_environment' /usr/local/bin/bash: parallel_bash_environment: line 67: unexpected EOF while looking for matching '' / usr / स्थानीय / बिन / bash के लिए फ़ंक्शन आयात परिभाषा: समानांतर_ bash_environment : लाइन 79: वाक्यविन्यास त्रुटि: अप्रत्याशित अंत file / usr / local / bin / bash: एरर के लिए फंक्शन डेफिनिशन इंपोर्ट करने में एर ...
निक

आपको शेल्टरफ़ॉर्क्ड किया गया है: शेलशॉक ने सीधे जीएनयू समानांतर को प्रभावित नहीं किया। शेलशॉक का समाधान, हालांकि, यह पूरी तरह से टूट गया --env और env_parallel ट्रिक। ऐसा माना जाता है कि इसे git संस्करण में तय किया गया है: git.savannah.gnu.org/cgit/parallel.git/snapshot/…
Ole Tange

1
मुझे यह उत्तर पसंद है, क्योंकि इसने मुझे समानांतर उपकरण की खोज की
JR Utily

10

कुछ इस तरह से भी काम करना चाहिए:

function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "

1

हो सकता है कि यह बुरा अभ्यास हो, लेकिन यदि आप एक .bashrcया अन्य स्क्रिप्ट में फ़ंक्शन को परिभाषित कर रहे हैं , तो आप फ़ाइल या कम से कम फ़ंक्शन परिभाषाओं की एक सेटिंग के साथ लपेट सकते हैं allexport:

set -o allexport

function funcy_town {
  echo 'this is a function'
}
function func_rock {
  echo 'this is a function, but different'
}
function cyber_func {
  echo 'this function does important things'
}
function the_man_from_funcle {
  echo 'not gonna lie'
}
function funcle_wiggly {
  echo 'at this point I\'m doing it for the funny names'
}
function extreme_function {
  echo 'goodbye'
}

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