简体   繁体   中英

How to run the bash script in parallel rather than sequentially?

#!/bin/bash

some_array=($1)

echo "-- Setting-Up VM --"

for i in ${some_array[@]}; do
    echo "VM #: $i"

    case "$i" in

        "1")
        echo "Setting-Up VM $i"
        sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@10.xx.x.xx <<EOF
        pwd
        nohup yes | /etc/rc.d/init.d/lifconfig
        su tarts
        nohup yes | vncserver
        sleep 10
        exit
        exit
EOF
        ;;

        "2")
        echo "Setting-Up VM $i"
        sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@10.xx.x.xx <<EOF
        pwd
        nohup yes | /etc/rc.d/init.d/lifconfig
        su tarts
        nohup yes | vncserver
        sleep 10
        exit
        exit
EOF
        ;;

        "3")
        echo "Setting-Up VM $i"
        sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@10.xx.x.xx <<EOF
        pwd
        nohup yes | /etc/rc.d/init.d/lifconfig
        su tarts
        nohup yes | vncserver
        sleep 10
        exit
        exit
EOF
        ;;
        *)
        echo "unknown VM!"
        ;;
    esac
done

Can someone please guide me I have the above script which is executed when we run the script for instance ./vmSetup.sh "1 2 3" but this is executed sequentially. I had created this script but now I want to run the cases in the script ie 1, 2 and 3 in parallel. Can someone also tell me how to run for instance 8 cases in parallel?

Put each case... esac statement in the background by ending it with & . Then use wait after the loop to wait for all the background processes to finish.

#!/bin/bash

some_array=($1)

echo "-- Setting-Up VM --"

for i in ${some_array[@]}; do
    echo "VM #: $i"

    case "$i" in

        "1")
        echo "Setting-Up VM $i"
        sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@10.xx.x.xx <<EOF
        pwd
        nohup yes | /etc/rc.d/init.d/lifconfig
        su tarts
        nohup yes | vncserver
        sleep 10
        exit
        exit
EOF
        ;;

        "2")
        echo "Setting-Up VM $i"
        sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@10.xx.x.xx <<EOF
        pwd
        nohup yes | /etc/rc.d/init.d/lifconfig
        su tarts
        nohup yes | vncserver
        sleep 10
        exit
        exit
EOF
        ;;

        "3")
        echo "Setting-Up VM $i"
        sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@10.xx.x.xx <<EOF
        pwd
        nohup yes | /etc/rc.d/init.d/lifconfig
        su tarts
        nohup yes | vncserver
        sleep 10
        exit
        exit
EOF
        ;;
        *)
        echo "unknown VM!"
        ;;
    esac &
done

wait

Why do you have a case statement at all when all these are identical?

#!/bin/bash
echo "-- Setting-Up VM(s) --"
for i in "$@"; do
case "$i" in
1) IP=1.2.3.4;;
2) IP=2.2.3.4;;
3) IP=3.2.3.4;;
*) echo "Invalid option '$i'" >&2; exit 1;;
esac
echo "Setting-Up VM $i"
sshpass -p root12 ssh -tt -o StrictHostKeyChecking=no root@$IP <<EOF &
  pwd
  nohup yes | /etc/rc.d/init.d/lifconfig
  su tarts
     nohup yes | vncserver
     sleep 10
     exit
  exit
EOF
done

To run a job in background, just use &

sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@$IP <<EOF &

It's just confusing because of the here-doc, but the & metacharacter still parses correctly on my system. Try it.

Also, rather than quoting all your options in one string and then parsing them back out to an array, why not just simplify the whole thing and let them come in as separate arguments? Call it as

./vmSetup.sh 1 2 3 # NOT "1 2 3" with quotes

and the loop becomes just

for i in "$@" # properly quoted, though wouldn't matter for 1 2 3

This whole thing seems a lot simpler and easier to maintain.

Another option, which is what I would do: create a file that is a list of the DNS/IP addresses you need, then pass that file as the lone argument.

#!/bin/bash
while read -r addr || [[ -n "$addr" ]]
do echo "Setting-Up VM $addr"
sshpass -p "root12"  ssh -tt -o StrictHostKeyChecking=no root@$addr <<EOF &
  pwd
  nohup yes | /etc/rc.d/init.d/lifconfig
  su tarts
     nohup yes | vncserver
     sleep 10
     exit
  exit
EOF
done < "$1"

Better, add valid error checking first to make sure the file exists and is readable, etc, but as a simple case, this should work.

For even better, cleaner, safer code, read https://mywiki.wooledge.org/BashFAQ/001 and follow those suggestions. :)

If ./vmSetup.sh 1 works as expected, these should work:

parallel -j8 ./vmSetup.sh {} ::: 1 2 3 ... 100
seq 100 | parallel -j8 ./vmSetup.sh

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM