Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

subprocess.check_output(): OSError file not found in Python

Tags:

python

Executing following command and its variations always results in an error, which I just cannot figure out:

command = "/bin/dd if=/dev/sda8 count=100 skip=$(expr 19868431049 / 512)"

print subprocess.check_output([command])

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 566, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

WHich file it is referring to ? other commands like ls,wc are running correctly though, the command is also running well on terminal but not python script.

like image 650
stackit Avatar asked Apr 27 '15 08:04

stackit


1 Answers

Your command is a list with one element. Imagine if you tried to run this at the shell:

/bin/'dd if='/dev/'sda8 count=100 skip=$(expr 19868431049 '/' 512)'

That's effectively what you're doing. There's almost certainly no directory named dd if= in your bin directory, and there's even more almost certainly no dev directory under that with an sd8 count=100 skip=$(expr 19868431049 directory with a program named 512 in it.

What you want is a list where each argument is its own element:

command = ['/bin/dd', 'if=/dev/sda8', 'count=100', 'skip=$(expr 19868431049 / 512)']
print subprocess.check_output(command) # notice no []

But that brings us to your second problem: $(expr 19868431049 / 512) isn't going to be parsed by Python or by dd; that's bash syntax. You can, of course, just do the same thing in Python instead of in bash:

command = ['/bin/dd', 'if=/dev/sda8', 'count=100', 
           'skip={}'.format(19868431049 // 512)]
print subprocess.check_output(command)

Or, if you really want to use bash for no good reason, pass a string, rather than a list, and use shell=True:

command = "/bin/dd if=/dev/sda8 count=100 skip=$(expr 19868431049 / 512)"
print subprocess.check_output(command, shell=True) # still no []

Although that still isn't going to work portably, because the default shell is /bin/sh, which may not know how to handle bashisms like $(…) (and expr, although I think POSIX requires that expr exist as a separate process…). So:

command = "/bin/dd if=/dev/sda8 count=100 skip=$(expr 19868431049 / 512)"
print subprocess.check_output(command, shell=True, executable='/bin/bash')
like image 114
abarnert Avatar answered Nov 01 '22 15:11

abarnert