user2503227
user2503227

Reputation: 137

python subprocess.check_output returns CalledProcessError on some commands

>>> import subprocess
>>> subprocess.check_output("smartctl -d ata -a /dev/sda", shell=True)
"output of above command prints normally"
>>> subprocess.check_output("smartctl -d ata -a /dev/sdb", shell=True)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/usr/lib/python2.7/subprocess.py", line 544, in check_output
       raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command 'smartctl -d ata -a /dev/sdb' returned non-zero exit status 64

Can anyone explain to me why the above command with sda works fine but returns an error with sdb? sdc works too, for the record. Also, I am aware of the risk of using shell=True. I am learning python and ran into this problem while writing a test script.

Upvotes: 1

Views: 3590

Answers (3)

Roland Smith
Roland Smith

Reputation: 43495

The smartctl command returns the value 64. According to the manual page the return value is a bitfield. Converting 64 to binary yields 01000000, so bit 6 is set (rightmost bit is bit 0). According to the aforementioned manpage:

Bit 6: The device error log contains records of errors.

If you can use Python 3.5, you could use the new high-level API subprocess.run(). This allows you to both capture return value and standard output/error.

prog = ['smartctl',  '-d', 'ata', '-a',  '/dev/sda']
result = subprocess.run(prog, stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
if result.returncode == 0:
    print(result.stdout)
else:
   print('smartctl returned error', result.returncode)

Upvotes: 1

Eugene Primako
Eugene Primako

Reputation: 2817

You can easily see what was wrong with sdb:

try:
    subprocess.check_output("smartctl -d ata -a /dev/sdb", shell=True)
except subprocess.CalledProcessError, e:
    print e.output

Upvotes: 2

vks
vks

Reputation: 67968

To know outputs and errors use

import subprocess
c=subprocess.Popen("smartctl -d ata -a /dev/sdb",stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
output,error=c.communicate()
#now check your error or output

Upvotes: 1

Related Questions