0

I am trying to read input from the user and store it in a variable by using subprocess.check_output in python2.7. But it shows up the error OSError: [Errno 2] No such file or directory when I try to run it. Also it is to be noted that I strictly want to use shell=False because of the security concerns.

I have tried subprocess.Popen and it doesnt work that way too. I have tried to use sys.stdin = open('/dev/tty', 'r') and stdin=subprocess.PIPE but give the same error as above.

>>> import sys
>>> import subprocess
>>> sys.stdin = open('/dev/tty', 'r')
>>> cmd = ('read userinput && echo "$userinput"')
>>> confirmation = subprocess.check_output(cmd.split(), stdin=sys.stdin).rstrip()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 567, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

The expected result is that it should ask for user input and store it to the confirmation variable

theJediCode
  • 112
  • 2
  • 12
  • Is there any particular reason you are not using `input()`? – Klaus D. Jan 17 '19 at 09:27
  • Actually I am using this in a `pre_push_hook.py` file which is a git hook. So when the script runs it is kind of copied to the `.git/hooks` directory and it runs in a git console. So when I tried to use `input()` (or `raw_input()`), it gave 'EOFError'. Actually I just tried and putting ` `sys.stdin.flush()` and `sys.stdin = open('/dev/tty', 'r')` did the trick and `raw_input()' worked as expected – theJediCode Jan 18 '19 at 06:04

1 Answers1

0

You are entering a shell command (read and echo are shell built-ins, and && is shell syntax), therefore you need shell=True. This is a single shell command, so you don't use the split. The parentheses around the command in python have no effect in this case:

import sys
import subprocess
sys.stdin = open('/dev/tty', 'r')

cmd = 'read userinput && echo "$userinput"'
confirmation = subprocess.check_output(cmd, stdin=sys.stdin, shell=True).rstrip()

print'****', confirmation

Gives:

$ python gash.py
hello
**** hello
cdarke
  • 42,728
  • 8
  • 80
  • 84
  • Hi @cdarke, Thanks for your answer. But I strictly need `shell=False` as there are security considerations; do you know any method I could do to perform my desired task? – theJediCode Jan 18 '19 at 05:46
  • What security considerations that don't apply to python scripts too? Bottom line is that you can't execute a shell command without using a shell. – cdarke Jan 18 '19 at 09:18
  • there are security considerations as also described [here](https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess) – theJediCode Jan 19 '19 at 04:40