英文:
Python subprocess.run inside Flask app failure [Errno 2] No such file or directory: 'ls': 'ls'
问题
使用subprocess.run()在Flask应用程序中需要什么?
即使是来自https://docs.python.org/3.6/library/subprocess.html 的简单示例也会失败。
process = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
output = process.stdout
app.logger.info(f"Process output: {output}")
错误信息如下:
File "./main.py", line 209, in process_pdf
process = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
File "/usr/lib/python3.6/subprocess.py", line 423, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1364, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'ls': 'ls'
Python 3.6.8(在Ubuntu 18.04LTS上)
Flask由uwsgi(来自nginx)提供服务
我尝试了更复杂的示例,尝试使用shell=True和其他参数,但似乎没有任何效果。
当从命令行sub.py调用时,subprocess.run()正常工作
process = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
output = process.stdout
print(f"Results {output}")
结果如下:
Results b'crw-rw-rw- 1 root root 1, 3 Nov 28 15:10 /dev/null\n'
在Flask中,我可以使用旧的os.popen,但没有结果
stream = os.popen('ls -l /dev/null')
output = stream.readlines()
app.logger.info(f"Process output: {output}")
编辑:感谢@furas和@Dursug指导我走上了正确的方向。对于www-data来说,似乎是缺少shell的问题。
那么,解决这个问题的最Pythonic/Flask方式是什么?
PS:我想运行特定的外部程序,如imagemagick、pdftotext,但我想避免包装器/绑定(有时没有)。
英文:
What is needed to use subprocess.run() inside a Flask app?
Even a simple example from https://docs.python.org/3.6/library/subprocess.html fails.
process = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
output = process.stdout
app.logger.info(f"Process output: {output}")
File "./main.py", line 209, in process_pdf
process = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
File "/usr/lib/python3.6/subprocess.py", line 423, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1364, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'ls': 'ls'
Python 3.6.8 (on Ubuntu 18.04LTS)
Flask is being served by uwsgi (from nginx)
I started from more complicated examples, trying with shell=True and other arguments, but nothing seems to be working.
subprocess.run() works just fine when called from command line sub.py
process = subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
output = process.stdout
print(f"Results {output}")
Results b'crw-rw-rw- 1 root root 1, 3 Nov 28 15:10 /dev/null\n'
Within Flask I can use old os.popen - no results though
stream = os.popen('ls -l /dev/null')
output = stream.readlines()
app.logger.info(f"Process output: {output}")
EDIT: Thanks to @furas and @Dursug for pointing me in the right direction. It seems like lack of shell issue for www-data.
So what would be the most Pythonic / Flask way of solving this?
PS I want to run specific external programs such as imagemagick, pdftotext, but I want to avoid wrappers/bindings (sometimes there are none).
答案1
得分: 1
这似乎确实是一个www-data用户的环境问题,该用户仅有访问Flask应用所在的虚拟环境路径的权限。
解决方法是编辑/etc/systemd/system/myproject.service
,添加:/usr/bin:/bin
,如下所示:
Environment="PATH=/home/myname/myproject/myprojectenv/bin:/usr/bin:/bin"
然后重新启动nginx和服务,如一个回答中建议的:
https://stackoverflow.com/questions/45906997/uwsgi-python-subprocess-chrome-firefox-failed。
问题仍然存在,即这是否是Flask的最佳实践。
从理论上讲,这可能会打开一个潜在的漏洞,如果客户端找到一种方式来运行任意命令。
英文:
This did turn out to be an enviroment issue for www-data which only had access to virtualenv path where Flask app was residing.
Solved by editing
/etc/systemd/system/myproject.service and adding :/usr/bin:/bin
as in
Environment="PATH=/home/myname/myproject/myprojectenv/bin:/usr/bin:/bin"
Then restarted nginx and service
As suggested by one of the answers on
https://stackoverflow.com/questions/45906997/uwsgi-python-subprocess-chrome-firefox-failed.
The question remains open whether this is the best practice for Flask.
Theoretically this opens up a potential vulnerability if client can find a way to run an arbitrary command.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论