Как запустить скрипт на python из памяти? - PullRequest
0 голосов
/ 18 октября 2018

Приложение, которое я пишу, извлекает сценарий оболочки через HTTP из сети, я хочу запустить этот сценарий на python, однако я не хочу физически сохранять его на жесткий диск, поскольку его содержимое уже находится в памяти, иЯ хотел бы просто выполнить это.Я пробовал что-то вроде этого:

import subprocess

script = retrieve_script()
popen = subprocess.Popen(scrpit, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdOut, stdErr = popen.communicate()

def retrieve_script_content():
    # in reality I retrieve a shell script content from network,
    # but for testing purposes I will just hardcode some test content here
    return "echo command1" + "\n" + "echo command2" + " \n" + "echo command3"

Этот фрагмент не будет работать, потому что subprocess.Popen ожидает, что вы будете предоставлять только одну команду за раз.

Есть ли альтернативы для запуска оболочкискрипт из памяти?

Ответы [ 3 ]

0 голосов
/ 18 октября 2018

Вы используете Unix-подобную ОС?Если это так, вы сможете использовать виртуальную файловую систему , чтобы создать файл-подобный объект в памяти, на который вы могли бы указать subprocess.Popen:

import subprocess
import tempfile
import os
import stat

def retrieve_script_content():
    # in reality I retrieve a shell script content from network,
    # but for testing purposes I will just hardcode some test content here
    return "echo command1" + "\n" + "echo command2" + " \n" + "echo command3"

content = retrieve_script_content()
with tempfile.NamedTemporaryFile(mode='w', delete=False, dir='/dev/shm') as f:
    f.write(content)
    os.chmod(f.name, stat.S_IRUSR | stat.S_IXUSR)
    # print(f.name)
popen = subprocess.Popen(f.name, stdout=subprocess.PIPE, stderr=subprocess.PIPE, 
                         shell=True)
stdOut, stdErr = popen.communicate()

print(stdOut.decode('ascii'))
# os.unlink(f.name)

print

command1
command2
command3

Выше я использовал /dev/shm в качестве виртуальной файловой системы, поскольку В системах Linux, основанных на Glibc, всегда есть tmpfs, смонтированные в / dev / shm .Если вас беспокоит безопасность, вы можете настроить ramfs .


Одна из причин, по которой вам может потребоваться использовать виртуальный файл вместо , передавая содержимое скрипта непосредственноsubprocess.Popen означает, что максимальный размер для одного строкового аргумента составляет , ограниченный 131071 байт .

0 голосов
/ 18 октября 2018

Этот фрагмент не будет работать, так как subprocess.Popen ожидает, что вы будете одновременно предоставлять только одну команду.

Это не так.Вместо этого причина, по которой он не работает:

  1. Объявление retrieve_script должно предшествовать вызову
  2. Вы называете его retrieve_script_content вместо retrieve_script
  3. Вы ошиблись script как scrpit

Просто исправьте это, и все нормально:

import subprocess

def retrieve_script():
    return "echo command1" + "\n" + "echo command2" + " \n" + "echo command3"

script = retrieve_script()
popen = subprocess.Popen(script, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdOut, stdErr = popen.communicate()
print(stdOut);

Результат:

$ python foo.py
command1
command2
command3

Однако учтите, что при этом игнорируется шебанг (если есть) и каждый раз запускается скрипт с sh системы.

0 голосов
/ 18 октября 2018

Вы можете выполнить много командный скрипт с Popen.Popen ограничивает вас только строкой из одной команды, когда флаг оболочки имеет значение False, но есть возможность передать список команд.Флаг Popen shell=True допускает использование нескольких командных сценариев (это считается небезопасным, хотя то, что вы делаете - выполнение сценариев из Интернета - уже очень рискованно).

...