2009-05-06 30 views
5

Cách tốt nhất/dễ nhất để xây dựng hệ thống xếp hàng nhiệm vụ tối thiểu cho Linux bằng cách sử dụng bash và các công cụ phổ biến là gì?Tối thiểu "Hàng đợi công việc" với các công cụ chứng khoán Linux để tận dụng CPU đa lõi

Tôi có tệp có 9'000 dòng, mỗi dòng có dòng lệnh bash, các lệnh hoàn toàn độc lập.

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

Hộp của tôi có nhiều lõi và tôi muốn thực hiện các tác vụ X cùng một lúc. Tôi đã tìm kiếm trên web một cách tốt để làm điều này. Rõ ràng, rất nhiều người có vấn đề này nhưng không ai có một giải pháp tốt cho đến nay.

Nó sẽ được tốt đẹp nếu các giải pháp có các tính năng sau:

  • thể giải thích nhiều hơn một lệnh (ví dụ command; command)
  • thể giải thích dòng chuyển hướng trên đường (ví dụ ls > /tmp/ls.txt)
  • chỉ sử dụng các công cụ Linux phổ biến

Điểm thưởng nếu nó hoạt động trên các bản sao Unix khác mà không yêu cầu quá kỳ lạ.

Trả lời

13

Bạn có thể chuyển đổi danh sách lệnh của mình thành Makefile không? Nếu vậy, bạn chỉ có thể chạy "make -j X".

+0

Tuyệt vời, điều này hoạt động như một sự quyến rũ! – Manuel

0

Được rồi, sau khi đăng câu hỏi ở đây, tôi đã tìm thấy dự án sau có vẻ đầy hứa hẹn: ppss.

Chỉnh sửa: Không hoàn toàn là những gì tôi muốn, PPSS tập trung vào việc xử lý "tất cả các tệp trong thư mục A".

0

Vâng, đây là một loại câu hỏi thú vị.

Đây là những gì tôi muốn làm, giả sử bash (1) tất nhiên.

  • tìm ra số lượng lệnh này có thể chạy một cách hữu ích đồng thời. Nó sẽ không chỉ là số lõi; rất nhiều lệnh sẽ bị treo cho I/O và loại điều đó. Hãy gọi số đó là N. N=15 chẳng hạn.
  • thiết lập trình xử lý tín hiệu bẫy cho tín hiệu SIGCHLD, xảy ra khi quá trình con chấm dứt. trap signalHandler SIGCHLD
  • cat danh sách lệnh của bạn vào một đường ống
  • viết một vòng lặp đọc stdin và thực hiện từng lệnh một, giảm bộ đếm. Khi bộ đếm là 0, nó là wait s.
  • trình xử lý tín hiệu của bạn, chạy trên số SIGCHLD, tăng bộ đếm đó.

Bây giờ, nó chạy lệnh N đầu tiên, sau đó chờ. Khi đứa trẻ đầu tiên chấm dứt, sự chờ đợi trở lại, nó đọc một dòng khác, chạy một lệnh mới và chờ đợi một lần nữa.

Bây giờ, đây là trường hợp cần nhiều công việc chấm dứt gần nhau.Tôi nghi ngờ bạn có thể nhận được ngay với một phiên bản đơn giản hơn:

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

Bây giờ, chương trình này sẽ bắt đầu lên 15 lệnh đầu tiên, và sau đó chạy phần còn lại cùng một lúc như một số chấm dứt lệnh.

0

Bạn có thể sử dụng lệnh xargs, --max-procs của bạn thực hiện những gì bạn muốn. Ví dụ Charlie Martin giải pháp trở nên với xargs:

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

chi tiết:

  • X là số tiến trình tối đa. Ví dụ: X = 15. max-procs đang làm sự kỳ diệu
  • tr đầu tiên được vào đây để chấm dứt dòng bằng byte null cho tùy chọn xargs --null để trích chuyển hướng vv không expansed sai
  • bash -c chạy lệnh

tôi đã thử nghiệm nó với điều này tập tin mycommands.sh ví dụ:

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

Đây là một trường hợp cụ thể, nhưng nếu bạn đang cố gắng để xử lý một tập hợp các tập tin và tạo ra một tập hợp các tập tin đầu ra, bạn có thể bắt đầu #cores số quy trình và kiểm tra xem tệp đầu ra có tồn tại trước khi chuyên nghiệp không dừng lại. Ví dụ dưới đây chuyển đổi một thư mục của file .m4b để .mp3 file:

Chỉ cần chạy lệnh này nhiều lần như bạn có lõi:

ls * M4B | khi đọc f; làm test -f $ {f% m4b} mp3 || mencoder -of rawaudio "$ f" -oac mp3lame -ovc copy -o $ {f% m4b} mp3; được thực hiện &

9

GNU Parallel http://www.gnu.org/software/parallel/ là công cụ tổng quát hơn để song song hơn PPSS.

Nếu runfile chứa:

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

bạn có thể làm:

cat runfile | parallel -j+0 

mà sẽ chạy một lệnh trên mỗi lõi CPU.

Nếu lệnh của bạn là đơn giản như trên, bạn thậm chí không cần runfile nhưng có thể làm:

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

Nếu bạn có nhiều máy tính có sẵn để làm việc xử lý bạn có thể muốn nhìn vào --sshlogin và --trc tùy chọn cho GNU Parallel.

0

công tác Queue + song song + Năng động Ngoài

Sử dụng một FIFO, kịch bản này ngã ba bản thân để xử lý hàng đợi. Bằng cách này, bạn có thể thêm lệnh vào hàng đợi khi đang di chuyển (khi hàng đợi đã được bắt đầu).

Cách sử dụng: ./queue lệnh [# của trẻ em] [Queue name]

Ví dụ, với 1 Chủ đề:

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

Output:

 
ONE 
TWO 

Ví dụ, với 2 chủ đề :

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

O utput:

 
TWO 
ONE 

Ví dụ, với 2 hàng đợi:

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

Output:

 
ONE queue2 
ONE queue1 

Các kịch bản (lưu nó dưới dạng "hàng đợi" và chmod + x hàng đợi):

 

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

Các vấn đề liên quan