在 shell 中将 python 参数作为数组传递

在 shell 中将 python 参数作为数组传递

在编写执行 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,或者只是从标准输入读取名称和路径。但这可能是自行车棚,最简单的实现也可能取决于实际源数据的格式,因此您可以做感觉最好的事情。)

相关内容