如何 运行 bash 脚本并行而不是顺序?
How to run the bash script in parallel rather than sequentially?
#!/bin/bash
some_array=()
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
有人可以指导我吗?我有上面的脚本,当我们 运行 脚本 ./vmSetup.sh "1 2 3"
时执行,但这是按顺序执行的。我已经创建了这个脚本,但现在我想 运行 脚本中的案例,即并行的 1、2 和 3。有人还可以告诉我如何 运行 例如并行处理 8 个案例吗?
将每个 case ... esac
语句以 &
结尾放在后台。然后在循环后使用wait
等待所有后台进程完成。
#!/bin/bash
some_array=()
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
当所有这些都相同时,为什么还要有 case 语句?
#!/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
要运行后台作业,只需使用&
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root@$IP <<EOF &
它只是因为这里的文档而令人困惑,但 &
元字符在我的系统上仍然可以正确解析。试试吧。
此外,与其在一个字符串中引用所有选项然后将它们解析回数组,为什么不简化整个事情并让它们作为单独的参数出现?称之为
./vmSetup.sh 1 2 3 # NOT "1 2 3" with quotes
循环就变成了
for i in "$@" # properly quoted, though wouldn't matter for 1 2 3
整个事情看起来更简单,更容易维护。
我会做的另一种选择:创建一个包含您需要的 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 < ""
最好先添加有效的错误检查以确保文件存在且可读等,但作为一个简单的案例,这应该可行。
要获得更好、更干净、更安全的代码,请阅读 https://mywiki.wooledge.org/BashFAQ/001 并遵循这些建议。 :)
如果 ./vmSetup.sh 1
按预期工作,这些应该工作:
parallel -j8 ./vmSetup.sh {} ::: 1 2 3 ... 100
seq 100 | parallel -j8 ./vmSetup.sh
#!/bin/bash
some_array=()
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
有人可以指导我吗?我有上面的脚本,当我们 运行 脚本 ./vmSetup.sh "1 2 3"
时执行,但这是按顺序执行的。我已经创建了这个脚本,但现在我想 运行 脚本中的案例,即并行的 1、2 和 3。有人还可以告诉我如何 运行 例如并行处理 8 个案例吗?
将每个 case ... esac
语句以 &
结尾放在后台。然后在循环后使用wait
等待所有后台进程完成。
#!/bin/bash
some_array=()
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
当所有这些都相同时,为什么还要有 case 语句?
#!/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
要运行后台作业,只需使用&
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root@$IP <<EOF &
它只是因为这里的文档而令人困惑,但 &
元字符在我的系统上仍然可以正确解析。试试吧。
此外,与其在一个字符串中引用所有选项然后将它们解析回数组,为什么不简化整个事情并让它们作为单独的参数出现?称之为
./vmSetup.sh 1 2 3 # NOT "1 2 3" with quotes
循环就变成了
for i in "$@" # properly quoted, though wouldn't matter for 1 2 3
整个事情看起来更简单,更容易维护。
我会做的另一种选择:创建一个包含您需要的 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 < ""
最好先添加有效的错误检查以确保文件存在且可读等,但作为一个简单的案例,这应该可行。
要获得更好、更干净、更安全的代码,请阅读 https://mywiki.wooledge.org/BashFAQ/001 并遵循这些建议。 :)
如果 ./vmSetup.sh 1
按预期工作,这些应该工作:
parallel -j8 ./vmSetup.sh {} ::: 1 2 3 ... 100
seq 100 | parallel -j8 ./vmSetup.sh