添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Python subprocess.run inside Flask app failure [Errno 2] No such file or directory: 'ls': 'ls' 。

0 人关注

在Flask应用中使用subprocess.run()需要什么?

即使是一个简单的例子,从 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 (on 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缺乏外壳的问题。

那么,什么才是解决这个问题的最Pythonic/Flask方式呢?

PS 我想运行特定的外部程序,如imagemagick、pdftotext,但我想避免包装器/绑定(有时没有)。

3 个评论
通常,像Apache/NGINX这样的网络服务器会以不同的用户 www-data ,不同的权限,在不同的文件夹,不同的环境下运行代码。所有这些都是为了安全。而且这个用户可能没有访问shell的权限。这也是为了安全。也许可以使用Python的方法,如 os.listsdir() os.stats()
@furas是对的,它看起来像是一个shell或$PATH问题。你有没有试过 ls 以外的命令或者用绝对路径?
当我在 /etc/passwd 中检查 www-data 时,显示该用户使用shell /usr/sbin/nologin ,这意味着它没有访问shell的权限。你可以尝试 run(['/bin/bash', 'ls'], shell=False) 。或者 run(["/bin/ls"], shell=False)
python
flask
subprocess
Sint
Sint
发布于 2020-01-03
1 个回答
Sint
Sint
发布于 2020-01-06
已采纳
0 人赞同

这确实是www-data的一个环境问题,它只能访问Flask应用所在的virtualenv路径。

Solved by editing

/etc/systemd/system/myproject.service并添加 :/usr/bin:/bin

Environment="PATH=/home/myname/myproject/myprojectenv/bin:/usr/bin:/bin"

然后重新启动了nginx和服务

正如一个答案所建议的