2009-05-06 5 views
5

bash 및 공용 도구를 사용하여 Linux 용 최소 작업 대기열 시스템을 구축하는 가장 좋은 방법은 무엇입니까?멀티 코어 CPU를 활용할 수있는 재고가있는 "작업 대기열"

9000 라인의 파일이 있는데, 각 라인에는 bash 명령 행이 있으며 명령은 완전히 독립적입니다.

command 1 > Logs/1.log 
command 2 > Logs/2.log 
command 3 > Logs/3.log 
... 

내 상자에는 여러 코어가 있으며 동시에 X 작업을 실행하려고합니다. 나는 이것을하기위한 좋은 방법을 찾았다. 분명히 많은 사람들이이 문제를 가지고 있지만 아무도 지금까지는 좋은 해결책이 없습니다.

솔루션은 다음과 같은 기능이 있다면 그것은 좋은 것 :

  • 하나 개 이상의 명령을 해석 할 수 있습니다 (예를 들어 command; command)
  • 은 스트림 해석 할 수는 라인에 리디렉션 (예 : ls > /tmp/ls.txt)
  • 만 일반적인 리눅스 도구를 사용합니다

이국적인 요구 사항이없는 다른 유닉스 클론에서 작동하는 경우 보너스 포인트가 필요합니다.

답변

13

명령 목록을 Makefile로 변환 할 수 있습니까? 그렇다면 "make -j X"를 실행할 수 있습니다.

+0

완벽하고 매력적이었습니다! – Manuel

0

여기에 질문을 게시 한 후, 나는 유망 해 보이는 다음 프로젝트를 발견했습니다 : ppss.

편집 : PPSS는 "디렉토리 A의 모든 파일"을 처리하는 데 중점을 둡니다.

0

어쨌든 이것은 재미있는 질문입니다.

여기에 제가 가정 할 경우, bash (1)을 가정합니다.

  • 이 명령어 중 얼마나 많은 명령어가 유용하게 동시에 실행될 수 있는지 파악하십시오. 코어 수만은 아닙니다. I/O 및 그런 종류의 명령에 대해 많은 명령이 일시 중단됩니다. 전화 번호 N. N=15 예를 들어.
  • 은 자식 프로세스가 종료 될 때 발생하는 SIGCHLD 신호에 대한 트랩 신호 처리기를 설정합니다. trap signalHandler SIGCHLD
  • cat 명령 목록을 파이프에 넣으십시오.
  • stdin을 읽고 명령을 하나씩 실행하여 카운터를 감소시키는 루프를 작성하십시오. 카운터가 0이면 wait입니다.
  • SIGCHLD에서 실행되는 사용자의 신호 처리기 은 해당 카운터 인을 증가시킵니다.

이제는 첫 번째 N 명령을 실행 한 다음 기다립니다. 첫 번째 자식이 종료되면 대기가 반환되고 다른 행을 읽고 새 명령을 실행 한 다음 다시 대기합니다.

이제는 가깝게 끝나는 많은 작업을 처리하는 경우입니다.당신은 간단한 버전으로 멀리 얻을 수 의심 :

N=15 COUNT=N cat mycommands.sh | while read cmd do eval $cmd & if $((count-- == 0)) then wait fi od 

지금,이 사람은 처음 15 개 명령을 시작하고 몇 가지 명령 종료로 한 번에 나머지 하나를 실행합니다.

0

당신은 당신이 원하는 것을의 xargs를에게 그것의 --max-발동을 명령을 사용할 수 있습니다. 예를 들어 찰리 마틴 솔루션은 xargs를 함께하게된다 :

tr '\012' '\000' <mycommands.sh |xargs --null --max-procs=$X bash -c 

세부 정보 :

  • X는 프로세스의 최대 수입니다. 예 : X = 15. --max-발동는 등 잘못 expansed되지 않은 리디렉션을 인용 있도록 xargs를 --null 옵션에 null 바이트로 라인을 종료 여기에 마법
  • 최초의 TR을하고있다
  • 명령을 실행 -c
  • bash는

나는 예를 들어이 mycommands.sh 파일로 테스트 :

date 
date "+%Y-%m-%d" >"The Date".txt 
wc -c <'The Date'.txt >'The Count'.txt 
0

이 특정 경우입니다,하지만 당신은 파일의 집합을 처리하고 출력 파일의 또 다른 세트를 생성하려는 경우, 당신은 시작할 수 있습니다 #cores 프로세스 수 및 프로 앞에 출력 파일이 있는지 확인하십시오. 그것을 끝내라. 당신이 코어를 가지고

그냥 많은이 명령을 실행 시간 : 아래의 예는 .m4b 파일의 디렉토리에 파일을 .MP3로 변환

LS * M4B을 | F를 읽는 동안; 테스트해라. -f $ {f % m4b} mp3 || mencoder-rawaudio "$ f"-oac mp3lame -ovc copy -o $ {f % m4b} mp3; done &

9

GNU 병렬 http://www.gnu.org/software/parallel/은 PPSS보다 병렬화하기위한보다 일반적인 도구입니다.

이 런 파일이 포함되어있는 경우 :

command 1 > Logs/1.log 
command 2 > Logs/2.log 
command 3 > Logs/3.log 

당신이 할 수 있습니다

cat runfile | parallel -j+0 

CPU 코어 당 하나 개의 명령을 실행한다.

당신의 명령을 당신도 런 파일이 필요하지 않지만 할 수있는 위와 같은 간단한 경우 : 당신이 처리를 수행 할 수 이상의 컴퓨터가있는 경우

seq 1 3 | parallel -j+0 'command {} > Logs/{}.log' 

당신이 --sshlogin보고 할 수 있으며, GNU 병렬 용 --trc 옵션.

0

당신은 내 작업 큐가 떠들썩한 파티에 작성 볼 수 있습니다 : FIFO를 사용

0

작업 대기열 + 병렬 + 동적 추가

https://github.com/pavelpat/yastq는이 스크립트 포크 자체가 큐를 처리 할 수 ​​있습니다. 이렇게하면 대기열에 명령을 즉시 추가 할 수 있습니다 (대기열이 이미 시작된 경우).

사용법 : ./queue 명령 [어린이 #] [대기열 이름]

예, 1 개 스레드 :

 
./queue "sleep 5; echo ONE" 
./queue "echo TWO" 

출력 :

 
ONE 
TWO 

예, 2 스레드 :

 
./queue "sleep 5; echo ONE" 2 
./queue "echo TWO" 

O utput :

 
TWO 
ONE 

예 2 큐와 :

 
./queue "sleep 5; echo ONE queue1" 1 queue1 
./queue "sleep 3; echo ONE queue2" 1 queue2 

출력 :

 
ONE queue2 
ONE queue1 

스크립트 ("큐"및 chmod를 + X 대기열로 저장)

 

    #!/bin/bash 

    #Print usage 
    [[ $# -eq 0 ]] && echo Usage: $0 Command [# of children] [Queue name] && exit 

    #Param 1 - Command to execute 
    COMMAND="$1" 

    #Param 2 - Number of childs in parallel 
    MAXCHILD=1 
    [[ $# -gt 1 ]] && MAXCHILD="$2" 

    #Param 3 - File to be used as FIFO 
    FIFO="/tmp/defaultqueue" 
    [[ $# -gt 2 ]] && FIFO="$3" 

    #Number of seconds to keep the runner active when unused 
    TIMEOUT=5 

    runner(){ 
     #Associate file descriptor 3 to the FIFO 
     exec 3"$FIFO" 

     while read -u 3 -t $TIMEOUT line; do 
     #max child check 
     while [ `jobs | grep Running | wc -l` -ge "$MAXCHILD" ]; do 
      sleep 1 
     done 

     #exec in backgroud 
     (eval "$line")& 
     done 
     rm $FIFO 
    } 

    writer(){ 
     #fork if the runner is not running 
     lsof $FIFO >/dev/null || ($0 "QueueRunner" "$MAXCHILD" "$FIFO" &) 

     #send the command to the runner 
     echo "$COMMAND" > $FIFO 
    } 

    #Create the FIFO file 
    [[ -e "$FIFO" ]] || mkfifo "$FIFO" 

    #Start the runner if in the runner fork, else put the command in the queue 
    [[ "$COMMAND" == "QueueRunner" ]] && runner || writer