我正在编写的应用程序通过HTTP从Network检索外壳程序脚本,我想在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
希望您一次只提供一个命令。
是否有其他选择可以从内存中运行Shell脚本?
答案 0 :(得分:2)
此代码段无效,因为子进程。Popen希望您一次只提供一个命令。
情况并非如此。相反,它不起作用的原因是:
retrieve_script
的声明必须在通话之前retrieve_script_content
而不是retrieve_script
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
运行脚本。
答案 1 :(得分:1)
您是否正在使用类似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
以上,自Linux systems based on Glibc always have a tmpfs mounted on /dev/shm起,我一直使用/dev/shm
作为虚拟文件系统。
如果出于安全考虑,您可能希望setup a ramfs。
您可能要使用虚拟文件而不是passing the script contents directly to subprocess.Popen
的一个原因是,单个字符串参数的最大大小为limited to 131071 bytes。
答案 2 :(得分:0)
您可以使用Popen执行多命令脚本。当shell标志为False时,Popen仅将您限制为一个命令字符串,但是可以传递命令列表。 Popen
的标志shell=True
允许使用多命令脚本(尽管您正在做的事情-从网络上执行脚本-已经非常危险,这被认为是不安全的)。