在编写执行 python 脚本的 shell 脚本时遇到这样的情况,该脚本使用传递的参数创建服务。希望能够将服务名称和配置作为数组传递,因为这些是创建服务时唯一会更改的值,其余参数保持不变。
运行下面的脚本时,它会创建 5 个不同的服务(有错误),因为每个参数都用作 1 个服务调用,并且错误表明其他参数丢失。下面的脚本中我缺少什么?是否有更好的方法来满足此要求?谢谢!
启动作业.sh
#!/bin/bash
#arguments
service=$1
config=$2
dockerv=$3
action=$4
file=$5
for addr in "$@"; do
for service in "$@"; do
for config in "$@"; do
python /scripts/serviceStart.py -s "$service" -c "$config" -d "$dockerv" -t "$action" "$addr"
done
done
done
调用脚本
/shellScripts/StartJobs.sh 720Test /720/config.xml 1080Test /1080/config.xml 5.6.0-1 Start 12.70.80.14
720Test and 1080Test ---service
/720/config.xml and 1080/config.xml ---config
每次运行 /shellScripts/StartJobs.sh 时都需要获取单个服务和单个配置值。上面指定了 2 个服务和 2 个相关配置。
期望 shell 脚本使用参数执行 python 脚本,并在同一 IP 上启动 2 个不同的服务,一个用于 720,一个用于 1080。
python /scripts/serviceStart.py -s 720Test -c /720/config.xml -d 5.6.0-1 -t Start 12.70.80.14
python /scripts/serviceStart.py -s 1080Test -c /1080/config.xml -d 5.6.0-1 -t Start 12.70.80.14
也尝试过此操作,但没有返回任何错误,也没有创建服务。
#!/bin/bash
args=()
while getopts ':d:t:' opt ; do
case $opt in
d) args+=( -d "$OPTARG" ) ;;
t) args+=( -t "$OPTARG" ) ;;
?) echo "Invalid option $OPTARG" ;;
:) echo "Option $OPTARG needs an argument" ;;
esac
done
myarray[0]= $service
myarray[1]= $config
for ((i=0; i<${#service[@]}; i++) && (j=0; j<${#config[@]}; j++)) ; do
echo $service
echo $config
python /scripts/serviceStart.py -s "${service[i]}" -c "${config[i]}" "${args[@]}" "$ip"
sleep 5
done
答案1
你写了:
希望能够将服务名称和配置作为数组传递
但这是不可能的,执行的程序获取单个列表/数组作为其命令行参数,因此无论如何,您都必须将所有数据放入该列表中。
在您的示例中,看起来您已经交错了不同类型的字段,并且您想要
StartJobs.sh 720Test /720/config.xml 1080Test /1080/config.xml 5.6.0-1 Start 12.70.80.14
产生命令
python serviceStart.py -s 720Test -c /720/config.xml -d 5.6.0-1 -t Start 12.70.80.14
python serviceStart.py -s 1080Test -c /1080/config.xml -d 5.6.0-1 -t Start 12.70.80.14
即规则似乎是列表中的最后三个参数用于每个Python调用( for -d
,-t
以及末尾的非选项参数),列表的其余部分一次使用两个参数( for-s
和-c
)。
现在,IMO,处理 N最后的args 特别听起来非常不常见(并且在 shell 中执行起来很尴尬,您只能将项目移出列表的开头,不能弹出最后一个),所以我建议在开头使用静态项目列表,或者更好的是,用于getopts
它们。所以:
#/bin/bash
while getopts ':d:t:a:' opt ; do
case $opt in
d) dockerv="$OPTARG" ;;
t) action="$OPTARG" ;;
a) addr="$OPTARG" ;;
?) echo "Invalid option $OPTARG" ;;
:) echo "Option $OPTARG needs an argument" ;;
esac
done
shift "$((OPTIND - 1))"
if (( $# % 2 == 1 )); then
echo >&2 "error: got odd number of args"
exit 1
fi
while [[ "$#" -gt 1 ]]; do
echo serviceStart.py -s "$1" -c "$2" -d "$dockerv" -t "$action" "$addr"
shift 2
done
进而
% bash startjobs.sh -d 5.6.0-1 -t Start -a 12.70.80.14 -- 720Test /720/config.xml 1080Test /1080/config.xml
serviceStart.py -s 720Test -c /720/config.xml -d 5.6.0-1 -t Start 12.70.80.14
serviceStart.py -s 1080Test -c /1080/config.xml -d 5.6.0-1 -t Start 12.70.80.14
(我仍然不确定将不同类型的值放入参数列表中是否是最好的做法,或者使用像 这样的分隔符单独的参数是否感觉更好1080Test:/1080/config.xml
,或者只是从标准输入读取名称和路径。但这可能是自行车棚,最简单的实现也可能取决于实际源数据的格式,因此您可以做感觉最好的事情。)