I am trying to use the subprocess to execute a command socat. It just echos the command as 'show stat | socat unix-connect:/users/viperias/Applications/haproxy.stat stdio' rather than printing the output of the command. It perfectly works for the other commands. Am I missing something?
def main():
cmd = "echo show stat | socat unix-connect:/users/viperias/Applications/haproxy.stat stdio"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print (output)
main()
Related
I'm having an issue running a simple python script that reads a helm command from a .sh script and outputs it.
When I run the command directly in the terminal, it runs fine:
helm list | grep prod- | cut -f5
# OUTPUT: prod-L2.0.3.258
But when I run python test.py (see below for whole source code of test.py), I get an error as if the command I'm running is helm list -f5 and not helm list | grep prod- | cut -f5:
user#node1:$ python test.py
# OUTPUT:
# Opening file 'helm_chart_version.sh' for reading...
# Running command 'helm list | grep prod- | cut -f5'...
# Error: unknown shorthand flag: 'f' in -f5
The test.py script:
import subprocess
# Open file for reading
file = "helm_chart_version.sh"
print("Opening file '" + file + "' for reading...")
bashCommand = ""
with open (file) as fh:
next(fh)
bashCommand = next(fh)
print("Running command '" + bashCommand + "'...")
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
if error is None:
print output
else:
print error
Contents of helm_chart_version.sh:
cat helm_chart_version.sh
# OUTPUT:
## !/bin/bash
## helm list | grep prod- | cut -f5
Try to avoid running complex shell pipelines from higher-level languages. Given the command you show, you can run helm list as a subprocess, and then do the post-processing on it in Python.
process = subprocess.run(["helm", "list"], capture_output=True, text=True, check=True)
for line in process.stdout.splitlines():
if 'prod-' not in line:
continue
words = line.split()
print(words[4])
The actual Python script you show doesn't seem to be semantically different from just directly running the shell script. You can use the sh -x option or the shell set -x command to cause it to print out each line as it executes.
If I run echo a; echo b in bash the result will be that both commands are run. However if I use subprocess then the first command is run, printing out the whole of the rest of the line.
The code below echos a; echo b instead of a b, how do I get it to run both commands?
import subprocess, shlex
def subprocess_cmd(command):
process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
proc_stdout = process.communicate()[0].strip()
print proc_stdout
subprocess_cmd("echo a; echo b")
You have to use shell=True in subprocess and no shlex.split:
import subprocess
command = "echo a; echo b"
ret = subprocess.run(command, capture_output=True, shell=True)
# before Python 3.7:
# ret = subprocess.run(command, stdout=subprocess.PIPE, shell=True)
print(ret.stdout.decode())
returns:
a
b
I just stumbled on a situation where I needed to run a bunch of lines of bash code (not separated with semicolons) from within python. In this scenario the proposed solutions do not help. One approach would be to save a file and then run it with Popen, but it wasn't possible in my situation.
What I ended up doing is something like:
commands = '''
echo "a"
echo "b"
echo "c"
echo "d"
'''
process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = process.communicate(commands)
print out
So I first create the child bash process and after I tell it what to execute. This approach removes the limitations of passing the command directly to the Popen constructor.
Join commands with "&&".
os.system('echo a > outputa.txt && echo b > outputb.txt')
If you're only running the commands in one shot then you can just use subprocess.check_output convenience function:
def subprocess_cmd(command):
output = subprocess.check_output(command, shell=True)
print output
>>> command = "echo a; echo b"
>>> shlex.split(command);
['echo', 'a; echo', 'b']
so, the problem is shlex module do not handle ";"
Got errors like when I used capture_output=True
TypeError: __init__() got an unexpected keyword argument 'capture_output'
After made changes like as below and its works fine
import subprocess
command = '''ls'''
result = subprocess.run(command, stdout=subprocess.PIPE,shell=True)
print(result.stdout.splitlines())
import subprocess
cmd = "vsish -e ls /vmkModules/lsom/disks/ | cut -d '/' -f 1 | while read diskID ; do echo $diskID; vsish -e cat /vmkModules/lsom/disks/$diskID/virstoStats | grep -iE 'Delete pending |trims currently queued' ; echo '====================' ;done ;"
def subprocess_cmd(command):
process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)
proc_stdout = process.communicate()[0].strip()
for line in proc_stdout.decode().split('\n'):
print (line)
subprocess_cmd(cmd)
I'm trying to run a subprocess from a Flask route, but I get a 500 error. It works when I run it directly from the shell. Why isn't it working?
import subprocess
from flask import Flask
app = Flask(__name__)
#app.route('/status/<vmid>')
def status(vmid):
cmd = "/usr/bin/virsh list --all | grep kvm%s | awk {'print $3'}" % vmid
p = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
out,err = p.communicate()
return out
if __name__ == '__main__':
app.run(host='0.0.0.0')
It raises a 500 error when run through Flask:
root#nc2-kvm:~# python status.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
(500 error)
It works when run directly in the shell:
root#nc2-kvm:~# virsh list --all | grep kvm180 | awk {'print $3'}
running
Take a look at
https://docs.python.org/2/library/subprocess.html
for subprocess.call to work in the form you're using, you would need to set the shell argument to True. To make sure it works, just try your subprocess.call in the python REPL first.
This question already has answers here:
AppleScript: how to get the current directory of the topmost Terminal
(3 answers)
Closed 8 years ago.
Is there a way in Python, subprocessing Bash and/or AppleScript, for me to get the current working directory of the frontmost Terminal.app tab and window in OSX?
I've tried the solution in AppleScript: how to get the current directory of the topmost Terminal. It doesn't work in my script.
I use Python to run AppleScript through the following function:
def run(script):
"Returns the result of running string in osascript (Applescript)"
if hasattr(script, "encode"): #Assumes Python 3
script = script.encode("utf-8")
osa = Popen(["osascript", "-"], stdout=PIPE, stdin=PIPE, stderr=PIPE)
results, err = osa.communicate(script)
if err:
raise Exception(err)
return results.decode("utf-8")
I have tried using the suggested answer through the following call:
def getTerminalDir():
script = '''
tell application "Terminal"
do shell script "lsof -a -p `lsof -a -c bash -u $USER -d 0 -n | tail -n +2 | awk '{if($NF==\"" & (tty of front tab of front window) & "\"){print $2}}'` -d cwd -n | tail -n +2 | awk '{print $NF}'"
end tell
'''
result = run(script)
return result
When I do that, I get the following error:
Exception: 126:127: syntax error: Expected end of line but found “"”. (-2741)
You can try something like:
tell application "Terminal"
if not (exists window 1) then reopen
activate
do script "pwd" in selected tab of window 1
set tabContents to contents of selected tab of window 1
end tell
set myPath to paragraph -2 of (do shell script "grep . <<< " & quoted form of tabContents)
Got it. Thanks for the useful AppleScript insights that helped lead to this solution, Zero.
from subprocess import Popen, PIPE, check_output, STDOUT
def runAppleScript(script):
"Returns the result of running string in osascript (Applescript)"
if hasattr(script, "encode"): #Assumes Python 3
script = script.encode("utf-8")
osa = Popen(["osascript", "-"], stdout=PIPE, stdin=PIPE, stderr=PIPE)
results, err = osa.communicate(script)
if err:
raise Exception(err)
return results.decode("utf-8")
def runBash(command):
output = check_output(command, stderr=STDOUT, shell=True)
return output
def getCurrentTerminalTTYS():
script = '''
tell application "Terminal"
return (tty of selected tab of front window)
end tell
'''
result = runAppleScript(script)
return result.strip()
def getPathForTTYS(ttys):
lsof = runBash('lsof').split('\n')
process = None
for line in lsof:
if ttys in line:
process = line.split()[1]
break
path = None
for line in lsof:
if 'cwd' in line and process in line:
path = ' '.join(line.split()[8:])
break
return path
def getCurrentTerminalPath():
ttys = getCurrentTerminalTTYS()
return getPathForTTYS(ttys)
This can be stored as a string using
path = getCurrentTerminalPath()
I am struggling to understand how to pipe commands using python.
What I want to do is:
echo 'subject:Hello World' | "/usr/bin/xxx -C -P Support\\XXX vmail"
I have tried this but it just throws the error "TypeError: bufsize must be an integer"
subprocess.call("echo","subject:xxx","|","/usr/bin/xxx","-C","-P","Support\\XXX","vmail")
Can this be done with python ?
Edit
I managed to get it to work using the 2 processes, but what about if I want to pipe a python object (email message) to an external program as an object rather than converting it to a string and echoing it ?
Use two processes and pipe them together.
import subprocess
with open("/tmp/out.txt", "w") as o:
p1 = subprocess.Popen(["date"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["cat"], stdin=p1.stdout, stdout=o)
This is equivalent to
$ date | cat > /tmp/out.txt
You can use subprocess.check_output with shell=True:
output=check_output("echo subject:Hello World | /usr/bin/xxx -C -P Support\\XXX vmail", shell=True)
here's an example:
>>> output=subprocess.check_output('echo subject:Hello World | tr [:lower:] [:upper:]', shell=True)
>>> output
'SUBJECT:HELLO WORLD\n'
You could do this:
import os
os.system('"subject:Hello World" | "/usr/bin/xxx -C -P Support\\XXX vmail"')