如何让本地 Python 脚本通过 SSH 将字典发送到远程 Python 脚本

问题描述 投票:0回答:1

理论上

我的目标是让一个在本地运行的 python 脚本(“s1.py”)通过远程计算机上的 ssh 启动第二个 python 脚本(“s2.py”)。作为启动 s2.py 的一部分,s1.py 将提供一个 python 字典,s2.py 会将其读入内存,并随后将其作为其必须执行的工作的一部分进行引用。该字典来自本地文件,出于安全原因,我希望将其保留在本地,因此想到通过线路将其发送到内存中(例如,我可以将文件复制到远程计算机的 tmpfs 空间,读取它并立即粉碎 tmpfs;这一切都会很快发生,但如果我可以在不发送文件的情况下发送数据,我仍然认为这是不好的做法)。

我一直采用的方法是基于这样的假设:我可以通过 ssh 将这个字典作为 python 对象以命令行项以及其他命令的形式从 s1.py 传递到 s2.py所需的行标志。比如:

ssh user@remote python3 s2.py python-dict-obj flag1 flag2

S2.py 然后会以某种方式读入对象(最好是字典),例如

useful_dict = sys.argv[1], var1_flag1=sys.argv[2], var2_flag2=sys.argv[2]

实践中

正如我提到的,字典来自本地文件,它同样可以存储在 yaml 或 json 中(yaml 更好)。因此 s1.py 可以使用标准 python 模块创建字典:

with open("local_file", "r", encoding="utf-8") as read_file:
    dict_from_file = json.load(read_file)

with open("local_file", 'r') as stream:
    dict_from_file = yaml.safe_load(stream)

S1.py 然后尝试通过 ssh 启动 s2.py 并发送字典,例如使用子进程模块:

subprocess.run(['ssh', 'user@remote', 'python3', '/user/scripts/s2.py', 'dict_from_file', 'flag1', 'flag2'])

问题/解决方案

出现问题是因为我尝试通过 ssh 发送字典吗? “dict_from_file”可以作为一个Python对象通过子进程模块并发送到远程计算机的环境/shell吗?使用 Paramiko 或 Fabric 时也一样吗?

迄今为止,我尝试过的任何操作似乎都让 s2.py 拒绝数据。这似乎表明可能根本不可能以我想要的方式传递字典。公平地说,我还没有尝试过任何比让 s2.py 使用 sys 模块在命令行接受输入更冒险的事情,所以也许有一种方法可以以不同的方式摄取数据。

即使无法通过 ssh 传输实际的字典对象,原始数据肯定可以以 json 格式发送吗?一个 json 字符串(json.dumps?)也许虽然我没有这方面的经验?那么,s2.py 大概可以读取字符串并重建字典?

或者,我的做法是不是太天真了?我是否需要探索套接字/管道/多进程来实现我想要做的事情。在基本层面上,我只是尝试执行一些简单的(我认为)数据传输,所以我希望有一种简短、优雅的方法来执行此操作。欢迎任何和所有建议。

json python-3.x dictionary ssh
1个回答
0
投票

这对我有用。 不过,也有一些注意事项。 如果 JSON 包含任何带单引号的字符串,这将不起作用。 不幸的是,解决这个问题会导致迷宫般的曲折通道。

import sys
import json
import subprocess

if len(sys.argv) > 1:
    x = json.loads(sys.argv[1])
    print('SUBPROCESS')
    print(sys.argv[1],flush=True)
    print(x)
else:
    s = json.load(open('x.json'))
    cmd = [ 'ssh', 'timr@localhost', 'python', __file__, "'"+json.dumps(s)+"'" ]
    print("MAIN")
    subprocess.run(cmd)

输出:

MAIN
SUBPROCESS
{"id": "123ab", "operation": "foo", "metadata": {"source": "ddb", "destination": "s3"}, "data": "02-02-2024"}
{'id': '123ab', 'operation': 'foo', 'metadata': {'source': 'ddb', 'destination': 's3'}, 'data': '02-02-2024'}

如果您有更复杂的输入,您可以通过标准输入输入文本:

import sys
import json
import subprocess

if len(sys.argv) > 1:
    print('SUBPROCESS')
    x = sys.stdin.read()
    print('file',x)
    y = json.loads(x)
    print('json',y)
else:
    s = json.load(open('x.json'))
    cmd = [ 'ssh', 'timr@localhost', 'python', __file__, 'x']
    print("MAIN")
    subprocess.run(cmd,input=json.dumps(s).encode())

输出:

SUBPROCESS
file {"id": "123ab", "operation": "foo", "metadata": {"source": "ddb", "destination": "s3"}, "data": "02-02-2024"}
json {'id': '123ab', 'operation': 'foo', 'metadata': {'source': 'ddb', 'destination': 's3'}, 'data': '02-02-2024'}
MAIN
© www.soinside.com 2019 - 2024. All rights reserved.