【问题标题】:How to run a shell script in python from memory?如何从内存中运行python中的shell脚本?
【发布时间】:2019-03-23 09:11:03
【问题描述】:

我正在编写的应用程序通过 HTTP 从网络检索 shell 脚本,我想在 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"

这个 sn-p 不起作用,因为 subprocess.Popen 期望您一次只提供一个命令。

有没有其他方法可以从内存中运行 shell 脚本?

【问题讨论】:

标签: python shell subprocess sh popen


【解决方案1】:

您可以使用 Popen 执行多命令脚本。当 shell 标志为 False 时,Popen 仅将您限制为一个命令字符串,但可以传递命令列表。 Popen 的标志 shell=True 允许使用多命令脚本(这被认为是不安全的,尽管您正在做的事情 - 从 Web 执行脚本 - 已经非常危险了)。

【讨论】:

  • 我们有一个 Web 服务,它为我们的应用程序提供 shell 脚本,所以我知道我在做什么,不用担心 :)
  • 答案解决了如何执行下载的多行脚本的一般问题,尽管确实不去查看示例代码。
【解决方案2】:

您使用的是类 Unix 操作系统吗?如果是这样,您应该能够 use a virtual filesystem 制作一个内存中的类似文件的对象,您可以将其指向 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)

打印

command1
command2
command3

上面我使用/dev/shm 作为虚拟文件系统,因为Linux systems based on Glibc always have a tmpfs mounted on /dev/shm。 如果您担心安全问题,您可能希望setup a ramfs


您可能想要使用虚拟文件而不是passing the script contents directly to subprocess.Popen 的一个原因是单个字符串参数的最大大小是limited to 131071 bytes

【讨论】:

  • 谢谢,代码将在树莓派上运行Rasbian Jessie OS
【解决方案3】:

这个 sn-p 不起作用,因为 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

但是,请注意,这将忽略 shebang(如果有)并每次使用系统的 sh 运行脚本。

【讨论】:

  • 这是一个错字,但我在这里发布了一个测试代码示例。我可以确认运行这样的 bash 脚本确实适用于 Linux。但是,当我在 Windows 上运行类似的代码时,它不起作用,因此您将无法像在 Windows 上那样运行 batch files
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多