Python Flask应用程序中的subprocess.run失败 [Errno 2] 没有这个文件或目录: ‘ls’: ‘ls’

huangapple go评论81阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2020年1月3日 23:44:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581398.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定