我正在使用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
我已将上述shell脚本放在单行JSON文档中,但这不起作用,我总是收到错误
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脚本。
答案 0 :(得分:3)
首先,考虑一下你是否真的需要JSON。在您的示例代码中,您创建一个JSON字符串,然后立即将其解码为Python dict。直接使用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脚本放在自己的文件中,然后打开文件以从中读取字符串。