【问题标题】:How to make a big shell script in a single line shell script in json document?如何在 json 文档中的单行 shell 脚本中制作一个大 shell 脚本?
【发布时间】:2014-01-24 19:25:28
【问题描述】:

我正在使用 Python 和 bash shell 脚本。我需要从 Python 脚本执行 shell 脚本。我成功地做到了。我需要在 JSON 字符串的单行中有一个 shell 脚本。

下面是一个示例,它适用于我在 JSON 文档中制作的简单 shell 脚本...

import os
import json
import subprocess

jsonData = '{"pp": [0,3,5,7,9], "sp": [1,2,4,6,8]}'
jj = json.loads(jsonData)

os.putenv( 'jj3', ' '.join( str(v) for v in jj['pp']  ) )
os.putenv( 'jj4', ' '.join( str(v) for v in jj['sp']  ) )

jsonStr = '{"script":"#!/bin/bash \\n echo Hello World \\n "}'

j = json.loads(jsonStr)

shell_script = j['script']

print "start"
proc = subprocess.Popen(shell_script, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
    print "Shell script gave some error"
    print stdout
else:
    print "end"
    print stdout

现在我有一个下面的 shell 脚本,我需要在 JSON 文档中用一行表示它,就像我在上面的 Hello World 用例中所做的那样。

#!/bin/bash
set -e

readonly PRIMARY=/tech01/primary
readonly SECONDARY=/tech02/secondary
readonly LOCATION=(machineA machineB)
readonly MAPPED_LOCATION=/bat/data/snapshot
HOSTNAME=$hostname

dir1=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[0]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
dir2=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[1]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)

echo $dir1
echo $dir2

length1=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[0]} "ls '$dir1' | wc -l")
length2=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[1]} "ls '$dir2' | wc -l")

echo $length1
echo $length2

if [ "$dir1" = "$dir2" ] && [ "$length1" -gt 0 ] && [ "$length2" -gt 0 ]
then
    rm -rf $PRIMARY/*
    rm -rf $SECONDARY/*
    for el in $primary_partition
    do
        scp david@${LOCATION[0]}:$dir1/weekly_8880_"$el"_5.data $PRIMARY/. || scp david@${LOCATION[1]}:$dir2/weekly_8880_"$el"_5.data $PRIMARY/.
    done
fi

我已经在这样的单行 JSON 文档中制作了上面的 shell 脚本,但这不起作用,我总是收到错误

jsonStr = '{"script":"#!/bin/bash \n set -e \n readonly PRIMARY=/tech01/primary \n readonly SECONDARY=/tech02/secondary \n readonly LOCATION=(machineA machineB) \n readonly MAPPED_LOCATION=/bat/data/snapshot \n HOSTNAME=$hostname \n dir1=$(ssh -o \"StrictHostKeyChecking no\" david@${LOCATION[0]} ls -dt1 \"$MAPPED_LOCATION\"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1) \n dir2=$(ssh -o \"StrictHostKeyChecking no\" david@${LOCATION[1]} ls -dt1 \"$MAPPED_LOCATION\"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1) \n echo $dir1 \n echo $dir2 \n length1=$(ssh -o \"StrictHostKeyChecking no\" david@${LOCATION[0]} \"ls \'$dir1\' | wc -l\") \n length2=$(ssh -o \"StrictHostKeyChecking no\" david@${LOCATION[1]} \"ls \'$dir2\' | wc -l\") \n echo $length1 \n echo $length2 \n if [ \"$dir1\" = \"$dir2\" ] && [ \"$length1\" -gt 0 ] && [ \"$length2\" -gt 0 ] \n then \n rm -rf $PRIMARY/* \n rm -rf $SECONDARY/* \n for el in $primary_partition \n do \n scp david@${LOCATION[0]}:$dir1/t1_weekly_1680_\"$el\"_200003_5.data $PRIMARY/. || scp david@${LOCATION[1]}:$dir2/t1_weekly_1680_\"$el\"_200003_5.data $PRIMARY/. \n done \n fi"}'

这是我得到的错误 -

ValueError: Invalid control character

谁能帮我解决我在做什么?在单行 JSON 文档中制作上述 shell 脚本的正确方法是什么?

更新:-

这里面还有另一个转折点,我认为值得一提..

我需要将此单行 shell 脚本数据存储在 Zookeeper 节点中。因此,对于 Hello World shell 脚本示例案例,我使用以下代码进行存储。我正在使用 Curator 库写入 Zookeeper。

client.create().creatingParentsIfNeeded().forPath("/be/wf/error1/v1/step1", "{\"description\":\"Hello World 1.\", \"script\":\"#!/bin/bash \\n set -e \\n echo Hello World 1 \\n\"}".getBytes());

然后我有我的 Python 程序来读取 Zookeeper 节点数据,然后通过从脚本标签中提取来执行 shell 脚本..

现在我尝试以上述格式表示答案中提到的相同脚本,并且我的 Eclipse 开始在字符串上给出编译错误。那么我如何表示上面答案中给出的shell脚本..

我想我真的需要一个 JSON,以便我可以将它正确存储在 Zookeeper 节点中,然后我的 Python 程序可以从节点读取相同的 JSON 数据并从脚本标签执行 shell 脚本。

【问题讨论】:

    标签: python linux bash shell subprocess


    【解决方案1】:

    首先,考虑您是否真的需要 JSON。在您的示例代码中,您创建了一个 JSON 字符串,然后立即将其解码为 Python 字典。直接使用dict会更简单吗?

    您当前字符串的问题是您没有正确转义引号。为避免混淆多级转义,请使用三引号字符串表示 shell 脚本,并使用json.dumps 将 dict 转换为 JSON 字符串:

    import json
    jsonstr = json.dumps({"script": """\
    #!/bin/bash
    set -e
    
    readonly PRIMARY=/tech01/primary
    readonly SECONDARY=/tech02/secondary
    readonly LOCATION=(machineA machineB)
    readonly MAPPED_LOCATION=/bat/data/snapshot
    HOSTNAME=$hostname
    
    dir1=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[0]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
    dir2=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[1]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
    
    echo $dir1
    echo $dir2
    
    length1=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[0]} "ls '$dir1' | wc -l")
    length2=$(ssh -o "StrictHostKeyChecking no" david@${LOCATION[1]} "ls '$dir2' | wc -l")
    
    echo $length1
    echo $length2
    
    if [ "$dir1" = "$dir2" ] && [ "$length1" -gt 0 ] && [ "$length2" -gt 0 ]
    then
        rm -rf $PRIMARY/*
        rm -rf $SECONDARY/*
        for el in $primary_partition
        do
            scp david@${LOCATION[0]}:$dir1/weekly_8880_"$el"_5.data $PRIMARY/. || scp david@${LOCATION[1]}:$dir2/weekly_8880_"$el"_5.data $PRIMARY/.
        done
    fi"""})
    

    或者,您可以将 shell 脚本放在它自己的文件中并打开文件以从中读取字符串。

    【讨论】:

    • 谢谢。这可能是一个愚蠢的问题。在 JSON 文档中,如果我有三重引号字符串,那么它是有效的 JSON 文档吗?
    • @SSH -- 不,JSON 不识别三引号字符串。这是 Python 的一个特性。但是,您可以使用三引号字符串创建 python 字典并将其转储到 JSON 文件中。
    • 这正是我要提议的。 +1
    • 你还能告诉我我在哪里将它解码为 Python 字典吗?我刚开始使用 Python,所以我还需要记住一些东西?
    • @SSH:这是json.loads 电话。
    猜你喜欢
    • 2019-02-10
    • 2021-06-03
    • 1970-01-01
    • 2012-01-11
    • 2013-04-18
    • 2015-07-22
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    相关资源
    最近更新 更多