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, 위험! 병렬 프로그래밍에 bash를 사용하지 마십시오. 많은 문제가 발생할 수 있습니다. C / C ++ 및 pthread, Java 스레드 또는 수행중인 작업에 대해 길고 힘들게 생각하는 것을 사용하십시오. 병렬 프로그래밍에는 많은 생각이 필요하기 때문입니다.
David Souther 2016 년

27
@DavidSouther 모든 그림 파일을 png로 변환하는 것과 같이 작업이 독립적 인 경우 걱정하지 마십시오. 동기화가 완료 될 때까지 기다립니다 (모두가 완료되기를 기다리는 것 이상).
ctrl-alt-delor

@DavidSouther-저는 오랫동안 Java 개발자이며 늦게까지 일하고 있습니다. 그리고 나는 사람들에게 계속해서 말합니다 : 친구들은 친구들이 bash 스크립트를 쓰지 못하게합니다. 그럼에도 불구하고, 나는이 포스트 / 솔루션을보고있다. (슬픈 얼굴 :() 나는 bash에서 병렬 처리에 종사하고있다. 나는 groovy / java에서 쉽게 할 수있다. 나쁘다!
Christian Bongiorno

답변:


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좋아하면 앞에 오는 명령으로 생성 될 수있는 모든 오류 값이 마스크됩니다. 또한 오류가 없으면 기본값이므로 약간 중복됩니다.

@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 "$@"' _ {}
$(date)

이는 주입 을 피하기 위해 매개 변수화 된 SQL 쿼리 를 사용하는 것과 비교할 수 있습니다.

내가 사용하고 date명령 치환 또는 탈출 따옴표 여기 대신에 rm이 비파괴 이후 사샤의 의견에 사용되는 명령.


14
조금 더 토론 : xargs는 명명 된 프로세스의 완전히 새로운 인스턴스를 실행합니다. 이 경우, echo_varPATH의 프로세스 (프로그램)가 아니라이 스크립트의 함수 인 name을 제공하십시오 . Dennis의 솔루션은 자식 bash 프로세스에서 사용할 기능을 내 보낸 다음 하위 프로세스로 분기하여 실행합니다.
David Souther 2016 년

7
의 중요성은 무엇 _이며 \, 그들 없이는 저에게 효과가 없었습니다
Hashbrown

9
@Hashbrown : 밑줄 ( _) 장소에 대한 홀더 제공 argv[0]( $0) 및이 사용할 수있는 거의 모든 것을. \;-exec절을 종료하는 데 사용하기 때문에 백 슬래시-세미콜론 ( )을 추가했다고 생각 find하지만 여기서는 그렇지 않습니다. 실제로 함수 $@대신에 함수를 사용 하는 $1경우 세미콜론을 매개 변수로 볼 수 있으므로 생략해야합니다.
추후 공지가있을 때까지 일시 중지되었습니다.

4
xargs에 대한 -i 인수는 더 이상 사용되지 않습니다. 대신 -I (자본 i)를 사용하십시오.
Nicolai S

11
with bash의 명령 문자열에 xargs의 인수를 포함시켜이를 단순화 할 수 있습니다 bash -c 'echo_var "{}"'. 따라서 마지막에 _ {}이 필요하지 않습니다.
공포증

16

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 {} 

osx에 대한 쇼핑을 어디에서받을 수 있습니까?
Nick

nvm 그것은 zsh에서 설정되어 있습니다
Nick

sh: parallel_bash_environment: line 67: unexpected EOF while looking for matching 오류 아래에서 가져 오기 Ole ''sh : parallel_bash_environment : 줄 79 : 구문 오류 : 예기치 않은 파일 끝 sh : parallel_bash_environment' /usr/local/bin/bash: parallel_bash_environment: line 67: unexpected EOF while looking for matching ''/ usr / local / bin / bash에 대한 함수 정의 가져 오기 오류 : parallel_bash_environment : 줄 79 : 구문 오류 : 예기치 않은 끝 파일 / usr / local / bin / bash :`...에 대한 함수 정의를 가져 오는 중 오류 발생
Nick

쉘 쇼크 쇼크 : 쉘 쇼크는 GNU Parallel에 직접 영향을 미치지 않았습니다. 그러나 쉘 쇼크에 대한 해결책은 다음과 같습니다. --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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.