Execute multiple shell scripts concurrently

前端 未结 5 681
Happy的楠姐
Happy的楠姐 2020-12-15 08:56

I want to do the following things:

  • Execute multiple shell scripts (here 2 scripts) concurrently.

  • Wait until both scripts finish

5条回答
  •  既然无缘
    2020-12-15 09:53

    If you have bash 4.2 or later available the following might be useful to you. It uses associative arrays to store task names and their "code" as well as task names and their pids. I have also built in a simple rate-limiting method which might come handy if your tasks consume a lot of CPU or I/O time and you want to limit the number of concurrent tasks.

    The script launches all tasks in the first loop and consumes the results in the second one.

    This is a bit overkill for simple cases but it allows for pretty neat stuff. For example one can store error messages for each task in another associative array and print them after everything has settled down.

    (I have copied this answer over from my answer here because it solves both questions, if that's not ok please tell me or replace it directly with just a link or whatever is suitable.)

    #! /bin/bash
    
    main () {
        local -A pids=()
        local -A tasks=([task1]="echo 1"
                        [task2]="echo 2"
                        [task3]="echo 3"
                        [task4]="false"
                        [task5]="echo 5"
                        [task6]="false")
        local max_concurrent_tasks=2
    
        for key in "${!tasks[@]}"; do
            while [ $(jobs 2>&1 | grep -c Running) -ge "$max_concurrent_tasks" ]; do
                sleep 1 # gnu sleep allows floating point here...
            done
            ${tasks[$key]} &
            pids+=(["$key"]="$!")
        done
    
        errors=0
        for key in "${!tasks[@]}"; do
            pid=${pids[$key]}
            local cur_ret=0
            if [ -z "$pid" ]; then
                echo "No Job ID known for the $key process" # should never happen
                cur_ret=1
            else
                wait $pid
                cur_ret=$?
            fi
            if [ "$cur_ret" -ne 0 ]; then
                errors=$(($errors + 1))
                echo "$key (${tasks[$key]}) failed."
            fi
        done
    
        return $errors
    }
    
    main
    

提交回复
热议问题