Вызов функций оболочки с помощью xargs
Я пытаюсь использовать 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 для этого, или любое другое решение (ы), приветствуются.
Ответы
Ответ 1
Экспорт функции должен сделать это (не проверено):
export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "[email protected]"' _ {}
Вы можете использовать встроенный printf
вместо внешнего seq
:
printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "[email protected]"' _ {}
Кроме того, использование return 0
и exit 0
подобным образом маскирует любое значение ошибки, которое может быть вызвано предшествующей ему командой. Кроме того, если ошибки нет, она используется по умолчанию и, следовательно, несколько избыточна.
@phobic упоминает, что команду Bash можно упростить до
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 "[email protected]"' _ {}
$(date)
Это сравнимо с использованием параметризованных SQL запросов, чтобы избежать внедрения.
Я использую date
в подстановке команд или в экранированных кавычках здесь вместо команды rm
, используемой в комментарии Саши, так как она неразрушающая.
Ответ 2
Использование GNU Parallel выглядит так:
#!/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 {}
Ответ 3
Что-то вроде этого тоже должно работать:
function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs [email protected] -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "
Ответ 4
Возможно, это плохая практика, но если вы определяете функции в .bashrc
или другом script, вы можете обернуть файл или, по крайней мере, определения функций с помощью параметра 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