将特殊字符作为args从python脚本传递到shell

时间:2018-07-20 15:24:26

标签: python-3.x shell parameter-passing

我有一个这样的config_file.yml文件:

sample:
    sql: "select * from dbname.tableName where sampleDate>='2018-07-20';"
    config: {'hosts': [!!python/tuple ['192.162.0.10', 3001]]}

sample2:
    sql: "select * from dbname.tableName where sampleDate<='2016-05-25';"
    config: {'hosts': [!!python/tuple ['190.160.0.10', 3002]]}

我的python代码是:

data_config = yaml.load(config_file)
for dataset, config in data_config.items():
    args = [config]
    cmd = ['./execute_something.sh']
    cmd.extend(args)
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).communicate()

execute_something.sh:

#!/bin/bash
echo $1
data_config=$1
echo $data_config

因此,基本上我想将整个字符串{'sql': "select * from dbname.tableName where sampleDate>='2018-07-20';", config: {'hosts': [!!python/tuple ['190.160.0.10', 3002]]}}作为参数传递给Shell脚本。

问题: 1)select *最终列出了当前目录中的所有文件,而不是完全以字符串形式传递 2)即使我传递了一个简单的字符串,说args="hi"仍然无效!

我不明白我在这里想念的是什么。请帮助。 谢谢!

1 个答案:

答案 0 :(得分:1)

请勿使用shell=True

data_config = yaml.load(config_file)
for dataset, config in data_config.items():
    cmd = ['./execute_something.sh', str(config)]
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()

运行shell=True时,您会将sh -c放在文字参数列表的前面。在这种情况下,将执行以下操作(将转义添加为单引号文字):

sh -c './execute_something.sh' '{'"'"'sql'"'"': "select * from dbname.tableName where sampleDate>='"'"'2018-07-20'"'"';", config: {'"'"'hosts'"'"': [!!python/tuple ['"'"'190.160.0.10'"'"', 3002]]}}'

那是行不通的。如果愿意,可以在shell中手动尝试。 为什么?因为以{开头的参数不会传递给./execute_something.sh,而是传递给执行sh -c 的shell。

如果您真的坚持保留shell=True,什么会起作用?比较以下内容:

sh -c './execute_something.sh "$@"' _ '{'"'"'sql'"'"': "select * from dbname.tableName where sampleDate>='"'"'2018-07-20'"'"';", config: {'"'"'hosts'"'"': [!!python/tuple ['"'"'190.160.0.10'"'"', 3002]]}}'

这里,-c之后的参数是一个shell脚本,它查看其参数,并将这些参数传递给execute_something.sh