Как отправить словарь с помощью локального Python-скрипта на удалённый Python-скрипт по SSH

Вопрос или проблема

В теории

Моя цель — чтобы локальный скрипт на python (“s1.py”) запускал второй скрипт на python (“s2.py”) через ssh на удаленной машине. В процессе запуска 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:

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

Проблемы / Решения

Возникает ли проблема из-за того, что я пытаюсь отправить словарь через ssh? Может ли “dict_from_file” существовать как объект python, проходя через модуль subprocess и отправляясь в окружение/оболочку удаленной машины? То же самое, когда используется Paramiko или Fabric?

На данный момент все, что я пробовал, кажется, приводит к тому, что s2.py отклоняет данные. Это может означать, что, возможно, не удается передать словарь так, как я хочу. Честно говоря, я не пробовал ничего более сложного, чем принимать ввод в командной строке в s2.py с использованием модуля sys, поэтому, возможно, существует способ загрузить данные другим способом.

Даже если невозможно передать реальный объект словаря через ssh, конечно, необработанные данные можно отправить в формате json? Возможно, json-строка (json.dumps?), хотя у меня нет опыта с этим? Тогда, предположительно, s2.py сможет прочитать строку и восстановить словарь?

Или мой подход просто слишком naивен? Нужно ли мне исследовать сокеты/трубопроводы/многопроцессность, чтобы добиться того, что я пытаюсь сделать. На базовом уровне я просто пытаюсь выполнить простую (как я думаю) передачу данных, так что я надеюсь, что есть краткий, элегантный способ это сделать. Все предложения приветствуются.

Ответ или решение

Чтобы отправить словарь из локального скрипта Python (s1.py) на удалённый скрипт Python (s2.py) через SSH, лучшим подходом будет сериализация словаря в формат JSON (или YAML), а затем передача этой сериализованной строки как аргумента командной строки. Давайте подробно рассмотрим, как это сделать.

Шаг 1: Подготовка локального скрипта (s1.py)

  1. Импортируйте необходимые модули:

    import json
    import subprocess
  2. Загрузите словарь из файла:

    with open("local_file.json", "r", encoding="utf-8") as read_file:
       dict_from_file = json.load(read_file)
  3. Сериализуйте словарь в строку JSON:

    json_dict = json.dumps(dict_from_file)
  4. Отправьте строку JSON на удалённый скрипт (s2.py) с помощью subprocess.run:

    subprocess.run(['ssh', 'user@remote', 'python3', '/path/to/s2.py', json_dict, 'flag1', 'flag2'])

Шаг 2: Создание удалённого скрипта (s2.py)

  1. Импортируйте необходимые модули:

    import json
    import sys
  2. Получите строку JSON и флаги из аргументов командной строки:

    json_string = sys.argv[1]  # Первая команда - это строка JSON
    var1_flag1 = sys.argv[2]    # Второй аргумент - флаг 1
    var2_flag2 = sys.argv[3]    # Третий аргумент - флаг 2
  3. Десериализуйте строку JSON обратно в словарь:

    useful_dict = json.loads(json_string)

Пример кода

Локальный скрипт s1.py:

import json
import subprocess

# Загрузка словаря из локального файла JSON
with open("local_file.json", "r", encoding="utf-8") as read_file:
    dict_from_file = json.load(read_file)

# Сериализация словаря в строку JSON
json_dict = json.dumps(dict_from_file)

# Отправка на удалённый скрипт
subprocess.run(['ssh', 'user@remote', 'python3', '/path/to/s2.py', json_dict, 'flag1', 'flag2'])

Удалённый скрипт s2.py:

import json
import sys

# Получение аргументов
json_string = sys.argv[1]
var1_flag1 = sys.argv[2]
var2_flag2 = sys.argv[3]

# Десериализация строки JSON в словарь
useful_dict = json.loads(json_string)

# Пример использования значений словаря и флагов
print("Полученный словарь:", useful_dict)
print("Флаг 1:", var1_flag1)
print("Флаг 2:", var2_flag2)

Заключение

Использование JSON позволяет передавать сложные структуры данных (такие как словари) между скриптами через SSH эффективно и безопасно. Основным шагом является сериализация данных в строку JSON в локальном скрипте и их десериализация в удалённом скрипте. Это решение должно решить вашу задачу без необходимости использования более сложных методов, таких как сокеты или потоки.

Оцените материал
Добавить комментарий

Капча загружается...