2012-06-12 12 views
92

Próbuję użyć xargs do wywołania bardziej złożonej funkcji równolegle.Wywoływanie funkcji powłoki za pomocą 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 

ta zwraca błąd

xargs: echo_var: No such file or directory 

pomysłów, w jaki sposób mogę korzystać z xargs do osiągnięcia tego celu, lub inne rozwiązanie (a) byłoby mile widziane.

+1

niebezpieczeństwo, user1148366, niebezpieczeństwo! Nie używaj bash do programowania równoległego - natrafisz na tak wiele problemów. Użyj C/C++ i pthreads, lub wątków Java, lub cokolwiek, co sprawia, że ​​długo i ciężko myślisz o tym, co robisz, ponieważ równoległe programowanie wymaga wiele przemyśleń, aby uzyskać właściwe wyniki. –

+17

@DavidSouther Jeśli zadania są niezależne, na przykład konwertuj wszystkie te pliki graficzne na png, nie martw się. Dzieje się tak, gdy masz synchronizację (poza oczekiwaniem na zakończenie) i komunikację, która staje się nieporządna. –

Odpowiedz

87

Eksportowanie funkcji powinien to zrobić (niesprawdzone):

export -f echo_var 
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "[email protected]"' _ {} 

Można użyć wbudowanego printf zamiast zewnętrznego seq:

printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "[email protected]"' _ {} 

również używając return 0 i exit 0 takiego maskuje wszelkie wartość błędu, która może zostać wywołana przez poprzedzające ją polecenie. Ponadto, jeśli nie ma błędu, jest to ustawienie domyślne, a zatem nieco zbędne.

+7

Trochę więcej dyskusji: xargs wykonuje całkowicie nową instancję procesu o nazwie. W tym przypadku podajesz nazwę 'echo_var', która jest funkcją w tym skrypcie, a nie proces (program) w twojej zmiennej PATH. Tym, co robi Dennis, jest eksportowanie funkcji wykorzystywanych przez procesy potomne, a następnie przekazywanie do podprocesu i tam wykonywanie. –

+4

jakie jest znaczenie '_' i' '\' ', bez nich to nie działało dla mnie – Hashbrown

+6

@ Haashown: Podkreślenie (' _') zapewnia miejsce dla 'argv [0]' ('$ 0 ') i prawie wszystko może być tam użyte. Myślę, że dodałem lewy ukośnik-półkolumny ('\;') z powodu jego użycia w kończeniu klauzuli "-exec" w 'find', ale działa on dla mnie bez tego tutaj. W rzeczywistości, gdyby funkcja użyła '$ @' zamiast '$ 1', to zobaczyłby średnik jako parametr, więc powinien zostać pominięty. –

12

Korzystanie GNU równoległy wygląda następująco:

#!/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 

Jeśli używasz wersji 20170822 nawet nie trzeba export -f tak długo, jak masz uruchomić to:

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

gdzie mogę dostać shopt dla osx? – Nick

+0

NVM jest setopt w zsh – Nick

+0

Getting to poniżej eerror Ole 'sh: parallel_bash_environment: Linia 67: nieoczekiwany EOF podczas poszukiwania dopasowanie' '' SH: parallel_bash_environment: Linia 79: błąd składni: nieoczekiwany koniec pliku sh: błąd importowanie definicji funkcji dla 'parallel_bash_environment ' /usr/local/bin/bash: parallel_bash_environment: linia 67: nieoczekiwany EOF podczas szukania dopasowania'' ' /usr/local/bin/bash: parallel_bash_environment: linia 79: błąd składni: nieoczekiwany koniec pliku /usr/local/bin/bash: definicja funkcji importowania błędów dla '... – Nick

5

Coś jak to powinno działa również:

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

Może to jest zła praktyka, ale jeśli jesteś zdeterminowany ing funkcje w .bashrc lub innego skryptu, można owinąć plik lub przynajmniej definicje funkcji z ustawieniem 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