如何将完整脚本内容存入变量并通过Python在远程服务器执行?
问题与解决方案
问题背景
我们有一个可执行的script.py,需要在该Python脚本中读取Shell脚本(示例为execution_count.ksh)的内容,并在另一台服务器上执行这些脚本。尝试用with open语句读取脚本内容存入datainfo变量,拼接ssh命令后通过os.system执行,但操作失败,现寻求可行方案。
原尝试的Python代码:
with open('script.sh', 'r') as file: datainfo = file.read() command="ssh user@192.168.1.101 "+ datainfo os.system(command)
示例Shell脚本(execution_count.ksh)内容:
exec 10<&0 exec < $1 # 记录输入文件名 in=$1 # 初始化 file="current_line.txt" let count=0 # 循环读取文件所有行 while read LINE do # 增加行计数器 ((count++)) # 将当前行写入临时文件$file(计数功能不需要这一步,仅作演示) echo $LINE > $file # 检查echo的返回码(写入不需要这一步,仅作演示) if [ $? -ne 0 ] then echo "写入文件${file}出错,请检查权限!" fi done echo "总行数: $count" echo "文件最后一行内容: `cat ${file}`" # 注:你也可以直接用wc工具实现相同功能 echo "预期总行数: `wc -l $in`" # 从文件描述符10恢复标准输入,并关闭文件描述符10 exec 0<&10 10<&-
原方法失败原因
直接将Shell脚本内容拼接进ssh命令字符串,会触发以下问题:
- 脚本中的换行、空格、特殊字符(如
$、反引号、>)会被本地Shell提前解析,导致远程执行的命令完全变形。 - 原Shell脚本中涉及标准输入重定向的逻辑(
exec < $1)无法正常工作,因为拼接后的命令无法正确传递参数和输入上下文。 os.system本身对复杂命令的参数处理能力弱,容易出现解析错误。
可行解决方案
方案一:通过标准输入传递脚本给SSH(推荐)
使用Python的subprocess模块,将Shell脚本内容通过标准输入传递给ssh命令,让远程Shell直接读取并执行完整脚本,避免本地解析问题。
修改后的Python代码:
import subprocess # 读取Shell脚本内容 with open('execution_count.ksh', 'r') as file: script_content = file.read() # 执行SSH命令,将脚本内容作为标准输入传递 # 注意:如果需要给Shell脚本传参数(比如原脚本的$1),要在ssh命令里指定 # 示例:如果要让远程脚本处理远程服务器上的/test.txt文件,命令改为['ssh', 'user@192.168.1.101', 'ksh', '-s', '/test.txt'] result = subprocess.run( ['ssh', 'user@192.168.1.101', 'ksh', '-s'], input=script_content.encode('utf-8'), capture_output=True, text=True ) # 打印执行结果 print("执行输出:", result.stdout) if result.stderr: print("错误信息:", result.stderr)
说明:
ksh -s表示让远程的ksh从标准输入读取脚本内容,同时可以在后面追加脚本需要的参数(如示例中的/test.txt对应原脚本的$1)。subprocess.run比os.system更安全,能更好地处理输入输出和错误。
方案二:先上传脚本到远程服务器再执行
如果脚本内容较大或需要重复执行,可以先通过scp将脚本上传到远程服务器,再执行:
import subprocess # 上传脚本到远程服务器的临时目录 subprocess.run(['scp', 'execution_count.ksh', 'user@192.168.1.101:/tmp/']) # 远程执行脚本,传递参数(比如远程的/test.txt) result = subprocess.run( ['ssh', 'user@192.168.1.101', 'ksh /tmp/execution_count.ksh /test.txt'], capture_output=True, text=True ) # 打印结果 print("执行输出:", result.stdout) if result.stderr: print("错误信息:", result.stderr) # 可选:执行完删除远程服务器上的脚本 subprocess.run(['ssh', 'user@192.168.1.101', 'rm /tmp/execution_count.ksh'])
内容的提问来源于stack exchange,提问作者Arya
相关产品推荐
相关产品推荐

