Search code examples
bashshellsshpidtail

Bash follow multi process returns


I have a bash script which launch multi process :

while read p || [[ -n $p ]]; do
    hostname=$(echo $p | cut -d';' -f1)
    # On lance les actions en background/parallele
    ssh "$hostname" "someAction.sh" > "$hostname.status.tmp" &
done < hostnames.prm 

The "someAction" script take some times on each server to launch. It returns steps progressively to tell what is going on.

I want to display progressively the state of each action on each process, refreshing the screen.

Example :

Hostname n°1 : 
Step 1 of someAction
Step 2 of someAction
...
Hostname n°2 : 
Step 1 of someAction
Step 2 of someAction
Step 3 of someAction
Step 4 of someAction
someAction finished
...
Hostname n°3 : 
Step 1 of someAction
...
Hostname n°4 : 
Step 1 of someAction
Step 2 of someAction
...
Hostname n°5 : 
Step 1 of someAction
Step 2 of someAction
Step 3 of someAction
Step 4 of someAction
someAction finished

So I store the progress steps return in one file by hostname with :

ssh "$hostname" "someAction..." > "$hostname.status.tmp" &

But then, how can I display them, while at least one process is in progress ?

It seems pretty much hard :/


Solution

  • Thank you for your answer.

    I just use :

        clear (go on top of screen)
        ...
        processing=1
    actionPids=()
    
    i=0
    while read p || [[ -n $p ]]; do
        hostname=$(echo $p | cut -d';' -f1)
        type=$(echo $p | cut -d';' -f2)
        if [[ "$type" = "$ENVIR" || "$ENVIR" = "ALL" || "$hostname" = "$ENVIR" ]]
        then
            # On lance les actions en background/parallele
            doInstance "$hostname" "$ACTION" > "$hostname.status.tmp" &
            actionPids[$i]=$!
        fi
        i=`expr $i + 1`
    done < hostnames.prm
    
    lastNbLines=0
    
    tput sc
    
    while [ $processing -eq 1 ]; do
            lastNbLinesTmp=$(cat *.status.tmp | wc -l)
            if [ $lastNbLinesTmp != $lastNbLines ]; then
                    tput rc
                    tput ed
                    echo "======================================================================================="
            fi
            while read p || [[ -n $p ]]; do
                    hostname=$(echo $p | cut -d';' -f1)
                    type=$(echo $p | cut -d';' -f2)
                    if [[ "$type" = "$ENVIR" || "$ENVIR" = "ALL" || "$hostname" = "$ENVIR" ]]
    then
                            if [ $lastNbLinesTmp != $lastNbLines ]; then
                                    echo -e "${cBold}Server $hostname :${cNone}"
                                    cat "$hostname.status.tmp"
                            fi
                    fi
            done < $OAAPATH/hostnames.prm
            processing=0
            for actionPid in "${actionPids[@]}"
            do
            if kill -0 $actionPid 2>/dev/null ; then
                    processing=1
            fi
            done
            **sleep 1**
            lastNbLines=$lastNbLinesTmp
    done
    
    # Wait for all process to finish before exit
    wait
    rm *.status.tmp
    
    [ $RET_SUM -ne 0 ] && exit 1
    exit 0
    

    it works perfectly.

    It's a bit complicated, but I think there is no real simplest solution.