Hey i'm trying to run a shell Script with python using the Following lines:
import subprocess
shellscript = subprocess.Popen(["displaySoftware.sh"], stdin=subprocess.PIPE)
shellscript.stdin.write("yes\n")
shellscript.stdin.close()
returncode = shellscript.wait()
But when I run the Program it says that it can't find the .sh file.
Your command is missing "sh", you have to pass "shell=True" and "yes\n" has to be encoded.
Your sample code should look like this:
import subprocess
shellscript = subprocess.Popen(["sh displaySoftware.sh"], shell=True, stdin=subprocess.PIPE )
shellscript.stdin.write('yes\n'.encode("utf-8"))
shellscript.stdin.close()
returncode = shellscript.wait()
This method might be better:
import subprocess
shellscript = subprocess.Popen(["displaySoftware.sh"], shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
returncode = shellscript.communicate(input='yes\n'.encode())[0]
print(returncode)
When running this on my machine the "displaySoftware.sh" script, that is in the same directory as the python script, is successfully executed.
Related
I would like to run a command in python using subprocess.run
I would like to switch the working directory JUST for the execution of this command.
Also, I need to record the output and the return code.
Here is the code I have:
import subprocess
result = subprocess.run("echo \"blah\"", cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
but this only returns
FileNotFoundError: [Errno 2] No such file or directory: 'echo "Running ls -la" && ls -la'
I also tried using the following arguments:
subprocess.run(["echo", "\"blah\""], cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Like Jean-François Fabre said, the solution is to add "shell=True" to the call
import subprocess
result = subprocess.run("echo \"blah\"", cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
shell=True seems to tell subprocess to use the string as a command.
I'm building a Flask application that allows a user to execute python scripts and see its output in the body of the http response.
The following code works but I'm not able to return the output of the child process to the father's in order to return a html response with the script output.
For example, in the app.py file I use the following code to run a subprocess that executes the client requested python script.
#app.route('/scripts/<script_name>')
def exec_script(script_name):
if os.path.isfile(os.path.join(app.config['SCRIPT_FOLDER'], script_name)):
result = subprocess.run(['python', os.path.join(app.config['SCRIPT_FOLDER'], script_name)], stdout=subprocess.PIPE, cwd=app.config['SCRIPT_FOLDER'])
print(result.stdout.decode('utf-8'))
# return HTML_PAGE
Let's suppose that the requested script example.pyspawns a process that executes a shell command, I'm not able to pass the output of the shell command to the process that was run in app.py
example.py
import subprocess
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
I guess that the reason why this is happening is that the process created in app.py is completed before the one created in the script. Is there a way to redirect the shell command output to the main application?
You can use subprocess.check_output
example:
result = subprocess.check_output(['ls', '-l'])
if result is not None:
print(result.decode('utf-8'))
Otherwise you can also try with subprocess.Popen:
result = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE).communicate()[0]
or:
p = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result, err = p.communicate()
print(result.decode('utf-8'))
I tried the following code which is working perfect, but it's not taking my passphrase. when I run this code I get a popup which asks to enter the passphrase for every time I run the python code in new cmd. But I want to automate this. So please suggest a better option to take passphrase for python script itself.
from subprocess import PIPE, Popen
output_file_name = 'abc.zip'
input_file_name = 'abc.zip.pgp'
args = ['gpg', '-o', output_file_name, '--decrypt', input_file_name]
proc = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE,shell=True)
proc.stdin.write('passphrase\n')
proc.stdin.flush()
stdout, stderr = proc.communicate()
print(stdout)
print(stderr)
Here's an example of the shell script:
python command_name.py --shell positional_arg1 positional_arg2 --option optional_arg1 --True_flag
I just want to be able to call this from a python script so I can loop through the script, changing different parameters through each loop.
import subprocess
p = subprocess.Popen(["python", "--shell", "positional_arg1", "positional_arg2",
"--option", "optional_arg1", "--True_flag"], shell=True,
stdout=subprocess.PIPE)
out, err = p.communicate()
There's a file named startup.cmd that sets some environment variables, runs some preparation commands, then does:
start "startup" cmd /k
Which opens a command shell named startup. The manual process I'm trying to automate is to then enter the following command into this shell: get startup.xml. I thought the correct way to do this in Python would be something like this:
import subprocess
p = subprocess.Popen('startup.cmd', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
getcommand = 'get startup.xml'
servercommand = 'startserver'
p.stdin.write(getcommand)
p.stdin.write(startserver)
(stdoutdata, stderrdata) = p.communicate()
print stdoutdata
print stderrdata
But those commands don't seem to be executing in the shell. What am I missing? Also, the command shell appears regardless of whether shell is set to True or False.
I found this warning in subprocess's document,
Warning Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.
So my suggestion is to use communicate to send your command.
import subprocess
p = subprocess.Popen('startup.cmd', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
command = 'get startup.xml\n'
command += 'startserver\n'
(stdoutdata, stderrdata) = p.communicate(command)
print stdoutdata
print stderrdata
This is a new process, so one cannot communicate directly with Popen.