简体   繁体   English

如何并行而不是顺序运行 bash 脚本?

[英]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.有人可以指导我我有上面的脚本,它在我们运行脚本时执行,例如./vmSetup.sh "1 2 3"但这是按顺序执行的。 I had created this script but now I want to run the cases in the script ie 1, 2 and 3 in parallel.我已经创建了这个脚本,但现在我想并行运行脚本中的案例,即 1、2 和 3。 Can someone also tell me how to run for instance 8 cases in parallel?有人还可以告诉我如何并行运行例如 8 个案例吗?

Put each case... esac statement in the background by ending it with & .将每个case... esac语句放在后台,并以&结尾。 Then use wait after the loop to wait for all the background processes to finish.然后在循环后使用wait等待所有后台进程完成。

#!/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.由于 here-doc,这只是令人困惑,但&元字符仍然在我的系统上正确解析。 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?此外,与其在一个字符串中引用所有选项,然后将它们解析回一个数组,为什么不简化整个事情,让它们作为单独的 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.另一种选择,这就是我要做的:创建一个文件,它是您需要的 DNS/IP 地址列表,然后将该文件作为唯一参数传递。

#!/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.要获得更好、更清洁、更安全的代码,请阅读https://mywiki.wooledge.org/BashFAQ/001并遵循这些建议。 :) :)

If ./vmSetup.sh 1 works as expected, these should work:如果./vmSetup.sh 1按预期工作,这些应该工作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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