Python subprocess.CalledProcessError: 返回非零退出状态2。

10
#!/usr/bin/env python
# encoding: utf-8

import re
import subprocess
import time
import json


def get_temperatures(disks):
    sensors = subprocess.check_output(["sensors"])
    temperatures = {match[0]: float(match[1]) for match in re.findall("^(.*?)\:\s+\+?(.*?)°C", 
                                            sensors, re.MULTILINE)}
    for disk in disks:
        output = subprocess.check_output(["smartctl", "-A", disk])
        temperatures[disk] = int(re.search("Temperature.*\s(\d+)\s*(?:\([\d\s]*\)|)$", 
                                            output, re.MULTILINE).group(1))
    return temperatures


def main():
    while True:
        print json.dumps(get_temperatures(("/dev/sda2", "/dev/sdb1")))
        time.sleep(20)


if __name__ == '__main__':
    main()

这是一个用Python监测温度的小脚本,使用smartmontools和lm-sensors。但是当我尝试运行它时,出现了错误。

subprocess.CalledProcessError: Command '['smartctl', '-A', '/dev/sda2']' returned non-zero exit status 2

但是当我在终端手动尝试这个命令时,它们能够正常工作。

一些信息:

uname -a 
Linux LME 4.0.0-040000-generic #201504121935 SMP Sun Apr 12 23:36:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

1
你的意思是“它们工作得很好”?当它们返回时,它们的退出代码是什么? - Eric Renouf
如果我在终端中输入smartctl -A /dev/sda,这将完美地工作。 - Konstantin Monahov
如果您紧接着运行 echo $?,它是否会打印 0 - Eric Renouf
是的,只有0,你有什么想法吗? - Konstantin Monahov
你是否以相同的用户身份运行两者?也许运行Python的用户没有权限打开/dev/sda2? - Eric Renouf
是的,同一个用户。我尝试使用sudo,但出现AttributeError: 'NoneType' object has no attribute 'group'错误。 - Konstantin Monahov
2个回答

11

如果被调用的进程返回任何非零退出代码,将会引发 CalledProcessError。在命令行上,您应该执行 echo $? 命令来获取最后的返回代码并查看它是否确实返回了 2。我怀疑它将会返回 2。

如果在 Python 代码中可以接受这种情况,您可以捕获 CalledProcessError 并从其属性内获得任何信息,特别是 output 属性。(在 Python 文档 中查找有关此错误的更多信息。)

示例:

import subprocess
output = None
try:
    output = subprocess.check_output(["smartctl", "-A", "/dev/sda2"])
except subprocess.CalledProcessError as e:
    output = e.output

我按照你说的修改了代码,现在出现了 AttributeError: 'NoneType' object has no attribute 'group' 的错误。➜ ~ echo $? 返回值为1。 - Konstantin Monahov
有趣的是你得到了不同的返回值。无论如何,你的NoneType错误几乎肯定是由于从你的re.search()调用中获得了一个None的返回值,这可能已经超出了这个问题的范围。 - BlackVegetable
1
@DavidArenburg 很好的发现。已修复。 - BlackVegetable

3
smartctl 的返回代码2意味着它无法打开设备。请确保运行Python代码的用户具有打开您想要检查的所有磁盘的权限。从 smartctl 的 man 页中的 RETURN VALUES 部分可知:

位1:设备打开失败,或设备未返回 IDENTIFY DEVICE 结构

因此我怀疑这真的是一个权限问题。我在我的系统上进行了验证。如果我运行 subprocess.check_output(['smartctl', '-A', '/dev/sda2']) ,会返回错误并返回2,但如果我运行subprocess.check_output(['sudo', 'smartctl', '-A', '/dev/sda2'])命令,则成功执行并且可以看到命令的输出。

现在运行后出现 AttributeError: 'NoneType' 对象没有属性 'group'。 - Konstantin Monahov
这意味着你现在已经得到了输出,但是你的正则表达式没有匹配到任何内容。 - Eric Renouf
我注意到关于正则表达式有一些问题,你可能需要查看一下。在Temperature后面的.*,你只是查找\s,但你可能想查找\s+。之后,你将不得不与自己的输出进行比较,因为我没有任何只包含数字和空格,然后以闭合括号和行尾的|结尾的行,实际上,对于我来说,smartctl -A根本没有任何|或任何括号。 - Eric Renouf
你需要在这个Python脚本上使用sudo来开始,对吧?(顺便说一句,回答很好。+1) - BlackVegetable
1
你可以在脚本中使用sudo,但如果这样做的话,你可能希望设置用户运行它时不需要密码来执行smartctl命令。 - Eric Renouf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接