隐藏 os.system 生成的控制台输出

Hiding console output produced by os.system

提问人:ArekBulski 提问时间:11/30/2015 更新时间:2/10/2023 访问量:54475

问:

我正在调用这段代码,但它在我运行 python 脚本的控制台中产生了一些输出(由于 tee 命令):

os.system("echo 3 | sudo tee /proc/sys/vm/drop_caches")

此版本不产生控制台输出,但有其他方法吗?

os.system('sudo bash -c "echo 3 > /proc/sys/vm/drop_caches"')
python 外壳

评论


答:

5赞 Alastair McCormack 11/30/2015 #1

直接写入 proc 伪文件,而是通过 Python i/o lib 写入。

这将要求您的脚本以 root 身份运行(via ),这意味着您应该将其范围限制为仅限管理员的工具。这也允许脚本在需要密码的盒子上运行。sudosudo

例:

with open("/proc/sys/vm/drop_caches", "w") as drop_caches:
    drop_caches.write("3")

评论

1赞 Anya Shenanigans 11/30/2015
我不会考虑将整个脚本作为解决方案作为根运行。
2赞 Alastair McCormack 11/30/2015
@Petesh,如果脚本需要 root 权限才能运行,则用户必须了解风险。在需要密码的系统上,OP 的原始脚本将失败。要求用户使用我的代码,会使风险和意图变得非常明显。sudosudo
1赞 ArekBulski 11/30/2015
Petesh,我们讨论的脚本已经需要 sudo 来调用命令。你的观点在这里无关紧要。
1赞 ArekBulski 11/30/2015
open("/proc/sys/vm/drop_caches", "w").write("3")也可以接受
38赞 mklement0 11/30/2015 #2

要根据问题的标题以最通用的形式回答问题:

禁止 os.system() 的所有输出请将 >/dev/null 2>&1 附加到 shell 命令中,这将使 stdout 和 stderr 都静音;例如:

import os
os.system('echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null 2>&1')

请注意,根据设计,调用进程的 stdout 和 stderr 流的输出会传递到控制台(终端)- 您的 Python 代码永远不会看到它们。os.system()

此外,如果 shell 命令失败,而是返回退出代码,则不会引发异常;请注意,提取 shell 命令的真正退出代码需要额外的工作:您需要通过应用从返回的 16 位值中提取高字节(尽管您可以依赖返回值而不是暗示错误条件)。os.system()>> 80


鉴于 的上述限制,通常值得改用子进程模块中的函数os.system()

例如,可以按如下方式使用:subprocess.check_output()

import subprocess
subprocess.check_output('echo 3 | sudo tee /proc/sys/vm/drop_caches', shell=True) 

以上将:

  • 捕获 stdout 输出并返回它(在上面的示例中忽略返回值)
  • 通过 STDERR 输出;作为附加参数传递也会捕获 stderr。stderr=subprocess.STDOUT
  • 如果 shell 命令失败,则引发错误。

注意:Python 3.5 引入了 ,两者都是更灵活的继任者 - 参见 https://docs.python.org/3.5/library/subprocess.html#using-the-subprocess-modulesubprocess.run()os.system()subprocess.check_output()


注意:

  • 尽管对 stdout 输出不感兴趣,但 OP 首先使用的原因是,在调用之前会解释使用代替的幼稚尝试,因此失败,因为尚未授予写入所需的权限。tee> ...sudo/proc/sys/...
  • 默认情况下,无论是使用函数还是函数,stdin 都不会受到影响,因此,如果您从终端调用脚本,则在遇到该命令时,您会收到交互式密码提示(除非已缓存凭据)。os.system()subprocesssudo
0赞 Shtefan 12/1/2019 #3

您也可以使用这种简单的子流程模块方法。

command = 'echo 3 | sudo tee /proc/sys/vm/drop_caches'
subprocess.check_call(shlex.split(command),stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL)

所有输出都将传递给 DEVNULL。该命令的任何问题都将由异常报告。没有问题意味着没有输出。

3赞 Meltrix 4/12/2022 #4
subprocess.check_call(command,stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

您忘了添加 stderr。

评论

0赞 Inaam Ilahi 9/19/2022
像魔术一样工作。谢谢