Can't quit while running long Popen command - python

I am running the below code which runs a command line application which runs for about 40 mins. While this is running my QUIT button is not accessible so I am unable to quit the running application. The below code and the button are both seated in their own def. Any ideas as to how I can get a working quit button while my application is running?
command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + logPath + " -s " + provider1 + " -v eXtreme"
master, slave = pty.openpty()
process = Popen(command1, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master)
global subject
subject = "Test"
while True:
wx.Yield()
line = stdout.readline()
line = line.rstrip()
print line
if "Returning 1" in line:
result1 = "Verify FAILED!"
subject = "FAILED! - "
self.sendEmail(self)
break
if "Returning 0" in line:
result1 = "Verify PASSED!"
subject = "PASSED! - "
self.sendEmail(self)
break

stdout.readline is blocking until there is something in stdout. You could use select module's poll
command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + logPath + " -s " + provider1 + " -v eXtreme"
master, slave = pty.openpty()
process = Popen(command1, shell=True, stdin=PIPE, stdout=master, stderr=slave, close_fds=True)
stdout = os.fdopen(master)
import select
q = select.poll()
q.register(stdout,select.POLLIN)
global subject
subject = "Test"
while True:
wx.Yield()
events = q.poll(0)
for fd, flags in events:
assert(fd == stdout.fileno())
line = stdout.readline()
print line
if "Returning 1" in line:
result1 = "Verify FAILED!"
subject = "FAILED! - "
self.sendEmail(self)
sys.exit(0)
if "Returning 0" in line:
result1 = "Verify PASSED!"
subject = "PASSED! - "
self.sendEmail(self)
sys.exit(0)

Related

RPi 3 Python Script - NameError: name 'BluetoothSocket' is not defined

So I am relatively new to python scripting and I came across this code that is supposed to configure wifi over bluetooth between a raspberry pi and smart device. Unfortunately, I keep running into the error listed in the title. I was hoping someone can copy and run the code and enlighten me why i keep running into this error. All help is greatly appreciated!
#!/usr/bin/env python
import os
from bluetooth import *
from wifi import Cell, Scheme
import subprocess
import time
wpa_supplicant_conf = "/etc/wpa_supplicant/wpa_supplicant.conf"
sudo_mode = "sudo "
def wifi_connect(ssid, psk):
# write wifi config to file
f = open('wifi.conf', 'w')
f.write('country=GB\n')
f.write('ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n')
f.write('update_config=1\n')
f.write('\n')
f.write('network={\n')
f.write(' ssid="' + ssid + '"\n')
f.write(' psk="' + psk + '"\n')
f.write('}\n')
f.close()
cmd = 'mv wifi.conf ' + wpa_supplicant_conf
cmd_result = ""
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
# restart wifi adapter
cmd = sudo_mode + 'ifdown wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
time.sleep(2)
cmd = sudo_mode + 'ifup wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
time.sleep(10)
cmd = 'iwconfig wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
cmd = 'ifconfig wlan0'
cmd_result = os.system(cmd)
print cmd + " - " + str(cmd_result)
p = subprocess.Popen(['ifconfig', 'wlan0'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate()
ip_address = "<Not Set>"
for l in out.split('\n'):
if l.strip().startswith("inet addr:"):
ip_address = l.strip().split(' ')[1].split(':')[1]
return ip_address
def ssid_discovered():
Cells = Cell.all('wlan0')
wifi_info = 'Found ssid : \n'
for current in range(len(Cells)):
wifi_info += Cells[current].ssid + "\n"
wifi_info+="!"
print wifi_info
return wifi_info
def handle_client(client_sock) :
# get ssid
client_sock.send(ssid_discovered())
print "Waiting for SSID..."
ssid = client_sock.recv(1024)
if ssid == '' :
return
print "ssid received"
print ssid
# get psk
client_sock.send("waiting-psk!")
print "Waiting for PSK..."
psk = client_sock.recv(1024)
if psk == '' :
return
print "psk received"
print psk
ip_address = wifi_connect(ssid, psk)
print "ip address: " + ip_address
client_sock.send("ip-addres:" + ip_address + "!")
return
try:
while True:
server_sock=BluetoothSocket( RFCOMM )
server_sock,bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "815425a5-bfac-47bf-9321-c5ff980b5e11"
advertise_service( server_sock, "RaspberryPiServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ],
protocols = [ OBEX_UUID ]
)
print("Waiting for connection on RFCOMM channel %d" % port)
client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info
handle_client(client_sock)
client_sock.close()
server_sock.close()
# finished config
print 'Finished configuration\n'
except (KeyboardInterrupt, SystemExit):
print '\nExiting\n'
This code outputs
Traceback (most recent call last): File "test.py", line 128, in <module>
server_sock=BluetoothSocket( RFCOMM )
NameError: name 'BluetoothSocket' is not defined
Can you show us your python version ?
Just type:
$ python --version
bluetooth lib seems to be present. But not BluetoothSocket: try to install bluez and python-bluez
$ sudo apt-get install bluez
$ sudo apt-get install python-bluez

python string replacement str type error dynamically building aws user-data script

The problem: I'm trying to dynamically build a python user-data script for amazon in a jenkins deploy script and pass it to an ASG to be executed at runtime. I pass my vars to the deploy script and then dynamically create the python script based on arguments.
I'm getting an unexpected string replacement error and I'm not entirely sure why handoff.sh is what passed the arguments from jenkins to the deploy script:
the error:
[deploy-and-configure-test] $ /bin/sh -xe /tmp/hudson8978997207867591628.sh
+ sh /var/lib/jenkins/workspace/deploy-and-configure-test/handoff.sh
Traceback (most recent call last):
File "/var/lib/jenkins/workspace/deploy-and-configure-test/asgBuilder.py", line 393, in <module>
''' % (str(repo), str(playbook),str(user_data_ins), str(in_user_data)))
TypeError: %u format: a number is required, not str
the dynamic portion of my deploy script:
in_user_data = args.in_user_data
playbook = args.playbook
repo = args.repo
user_data_ins = ('''export CLOUD_ENVIRONMENT=%s\n
export CLOUD_MONITOR_BUCKET=%s\n
export CLOUD_APP=%s\n
export CLOUD_STACK=%s\n
export CLOUD_CLUSTER=%s\n
export CLOUD_AUTO_SCALE_GROUP=%s\n
export CLOUD_LAUNCH_CONFIG=%s\n
export EC2_REGION=%s\n
export CLOUD_DEV_PHASE=%s\n
export CLOUD_REVISION=%s\n
export CLOUD_DOMAIN=%s\n
export SG_GROUP=%s\n''' % (cloud_environment,
cluster_monitor_bucket,
cluster_name,
cloud_stack,
cloud_cluster,
cloud_auto_scale_group,
cloud_launch_config,
provider_region,
cloud_dev_phase,
cloud_revision,
cloud_domain,
export_env_sg_name))
user_data_ins = ('''
#!/usr/bin/python
import os
import subprocess
import time
import uuid
def shell_command_execute(command):
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
print output
return output
repo = "%s"
playbook = "%s"
echo_bash_profile = "echo %s >> ~/.bash_profile" % user_echo
shell_command_execute(echo_bash_profile)
var_user_data = "%s"
for varb in var_user_data.split('|'):
echo_bash_profile_passed = "echo " + varb + " >> ~/.bash_profile"
shell_command_execute(echo_bash_profile_passed)
command = 'git clone ' + repo
shell_command_execute(command)
folder = repo.split('/')[4].replace('.git','')
#https://github.com/test/test.git # replaced for security.
execute_playbook = ('ansible-playbook -i "localhost," -c local' + '/' + os.path.dirname(os.path.realpath(__file__)) + '/' + folder + '/' + playbook >> ansible.log')
print execute_playbook
shell_command_execute(execute_playbook)
''' % (str(repo), str(playbook),str(user_data_ins), str(in_user_data)))
text_file = open("user-data.py", "wa")
text_file.write(user_data_ins)
text_file.close()
lc_user_data = '${file("%s/user-data.py")}' %wd
updated still not working
user_data_ins = ('''export CLOUD_ENVIRONMENT=%s\n
export CLOUD_MONITOR_BUCKET=%s\n
export CLOUD_APP=%s\n
export CLOUD_STACK=%s\n
export CLOUD_CLUSTER=%s\n
export CLOUD_AUTO_SCALE_GROUP=%s\n
export CLOUD_LAUNCH_CONFIG=%s\n
export EC2_REGION=%s\n
export CLOUD_DEV_PHASE=%s\n
export CLOUD_REVISION=%s\n
export CLOUD_DOMAIN=%s\n
export SG_GROUP=%s\n''' % (cloud_environment,
cluster_monitor_bucket,
cluster_name,
cloud_stack,
cloud_cluster,
cloud_auto_scale_group,
cloud_launch_config,
provider_region,
cloud_dev_phase,
cloud_revision,
cloud_domain,
export_env_sg_name))
user_data_ins = ('''
#!/usr/bin/python
import os
import subprocess
import time
import uuid
def shell_command_execute(command):
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
print output
return output
repo = "%s"
playbook = "%s"
echo_bash_profile = "echo %s >> ~/.bash_profile" % user_echo
shell_command_execute(echo_bash_profile)
var_user_data = "%s"
for varb in var_user_data.split('|'):
echo_bash_profile_passed = "echo " + varb + " >> ~/.bash_profile"
shell_command_execute(echo_bash_profile_passed)
command = 'git clone ' + repo
shell_command_execute(command)
folder = repo.split('/')[4].replace('.git','')
#https://github.com/zukeru/vision_provis.git
execute_playbook = ('ansible-playbook -i "localhost," -c local' + '/' + os.path.dirname(os.path.realpath(__file__)) + '/' + folder + '/' + playbook >> ansible.log')
print execute_playbook
shell_command_execute(execute_playbook)
''' % (str(repo), str(playbook),str(user_data_ins), str(in_user_data)))
text_file = open("user-data.py", "wa")
text_file.write(user_data_ins)
text_file.close()
lc_user_data = '${file("%s/user-data.py")}' %wd
#Grant Zukel
I would recommend doing the following.
In the last line change to
'''.format (str(repo), str(playbook),str(user_data_ins), str(in_user_data)))
And in your code change your first %s to {0} which would be str(repo) and every subsequent would be {1}... {2} etc
The problem is you have string replacement inside the string.
Whenever you have this, you need to have double percent:
echo_bash_profile = "echo %s >> ~/.bash_profile" %% user_echo
It is this line that is causing the error
'''bash_profile % user_echo'''
I would recommend using the string.format method if you are using python 2.6 or higher
Try this:
user_data_ins = ('''
#!/usr/bin/python
import os
import subprocess
import time
import uuid
def shell_command_execute(command):
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
print output
return output
repo = "{0}"
playbook = "{1}"
echo_bash_profile = "echo {2} >> ~/.bash_profile" % user_echo
shell_command_execute(echo_bash_profile)
var_user_data = "{3}"
for varb in var_user_data.split('|'):
echo_bash_profile_passed = "echo " + varb + " >> ~/.bash_profile"
shell_command_execute(echo_bash_profile_passed)
command = 'git clone ' + repo
shell_command_execute(command)
folder = repo.split('/')[4].replace('.git','')
#https://github.com/zukeru/vision_provis.git
execute_playbook = ('ansible-playbook -i "localhost," -c local' + '/' + os.path.dirname(os.path.realpath(__file__)) + '/' + folder + '/' + playbook >> ansible.log')
print execute_playbook
shell_command_execute(execute_playbook)
'''.format(str(repo), str(playbook),str(user_data_ins), str(in_user_data)))
This line seems to be causing the issue:
echo_bash_profile = "echo %s >> ~/.bash_profile" % user_echo
Likely it sees the % user as %u.
Ok so #FirebladDan you were right i miseed one here is the working code:
user_data_ins = ('''
#!/usr/bin/python
import os
import subprocess
import time
import uuid
def shell_command_execute(command):
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
print output
return output
repo = "%s"
playbook = "%s"
echo_bash_profile = "echo " + %s + " >> ~/.bash_profile"
shell_command_execute(echo_bash_profile)
var_user_data = "%s"
for varb in var_user_data.split('|'):
echo_bash_profile_passed = "echo " + varb + " >> ~/.bash_profile"
shell_command_execute(echo_bash_profile_passed)
command = 'git clone ' + repo
shell_command_execute(command)
folder = repo.split('/')[4].replace('.git','')
#https://github.com/zukeru/vision_provis.git
execute_playbook = ('ansible-playbook -i "localhost," -c local' + '/' + os.path.dirname(os.path.realpath(__file__)) + '/' + folder + '/' + playbook >> ansible.log')
print execute_playbook
shell_command_execute(execute_playbook)
''' % (str(repo), str(playbook),str(user_data_ins), str(in_user_data)))
text_file = open("user-data.py", "wa")
text_file.write(user_data_ins)
text_file.close()
lc_user_data = '${file("%s/user-data.py")}' %wd

Stuck in while True loop python

I am stuck in a while True loop which I can't seem to break, any suggestions please:
command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "/VerifyLog.txt -s " + provider1 + " -v eXtreme"
master, slave = pty.openpty()
process = Popen(command1, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master)
while True:
wx.Yield()
line = stdout.readline()
print line.rstrip()
if not line:
break
process.wait()
The simplest explanation is that you never get an empty line from stdout. Note that print line.rstrip() does not modify line; for example, if the last line ended with a newline, the loop would continue.
Sorted. I know that at the end of the last line it will return one of two strings so just needed to search for either of these two:
process = Popen(command1, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master)
while True:
wx.Yield()
line = stdout.readline()
line = line.rstrip()
print line
if "Returning 1" in line:
break
if "Returning 0" in line:
break

subprocess.Popen give real-time feedback in python

I have the below command in my python script running a command line application which is currently running 'blind' in the background. If I run this command from a command line, mac or PC, I get a real-time readout of that application running, as it runs for 40 mins+ and reports various different info while it is running. Currently as I say it runs blind and gives me all the info at the end on a readout in python, but I want it to essentially open a command line and run so I can see all the info in real-time, but i can't find a way to do this. Here is my current code using a subprocess.Popen. Any other ways?
command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "\\VerifyLog.txt -s " + provider1 + " -v eXtreme"
process = subprocess.Popen(command1, stdout=subprocess.PIPE, shell=True)
I wrote about this a few years ago, but I don't think I titled the article very well:
http://www.blog.pythonlibrary.org/2010/06/05/python-running-ping-traceroute-and-more/
Basically you need to redirect stdout. I usually do something like this:
class RedirectText:
def __init__(self,aWxTextCtrl):
self.out=aWxTextCtrl
def write(self,string):
self.out.WriteText(string)
And then in my actual wx class, I do something like this in the init:
self.redir=RedirectText(log)
sys.stdout=self.redir
Then when you call subprocess, you would do something like this example:
def pingIP(self, ip):
proc = subprocess.Popen("ping %s" % ip, shell=True,
stdout=subprocess.PIPE)
print
while True:
line = proc.stdout.readline()
wx.Yield()
if line.strip() == "":
pass
else:
print line.strip()
if not line: break
proc.wait()
Note the wx.Yield() call. That allows wxPython to update when we print the line to stdout, which we have redirected to a text control.
Here is an example of sorts:
import subprocess
import sys
import wx
class RedirectText:
def __init__(self,aWxTextCtrl):
self.out=aWxTextCtrl
def write(self,string):
self.out.WriteText(string)
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Test")
panel = wx.Panel(self)
log = wx.TextCtrl(panel, wx.ID_ANY, size=(300,100),
style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
btn = wx.Button(panel, label="Run")
btn.Bind(wx.EVT_BUTTON, self.onRun)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer)
self.redir=RedirectText(log)
sys.stdout=self.redir
#----------------------------------------------------------------------
def onRun(self, event):
""""""
command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "\\VerifyLog.txt -s " + provider1 + " -v eXtreme"
process = subprocess.Popen(command1, stdout=subprocess.PIPE, shell=True)
while True:
line = process.stdout.readline()
wx.Yield()
print line
if not line:
break
process.wait()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
frame.Show()
app.MainLoop()
I go it to work by changing this section from Mikes answer, but only trouble is now when the application ends and the output finishes printing lines my python freezes. Any ideas why?
def onRun(self, event):
""""""
command1 = transporterLink + " -m verify -f " + indir1 + " -u " + username + " -p " + password + " -o " + indir1 + "\\VerifyLog.txt -s "
+ provider1 + " -v eXtreme"
master, slave = pty.openpty()
process = Popen(command1, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master)
while True:
line = stdout.readline()
wx.Yield()
print line.rstrip()
if not line:
break
process.wait()

python multithreaded ssh app

I have an app I've scraped together to try and spawn 3 threads and ssh into a server simultaneously.
I wrote an obviously offensively coded application which I know is wrong which I am looking for some guidance for, to accomplish my initial end goal as mentioned above.
For the argument passing, I know I need to finesse it with something like cmd or cmd2 later on but for now that's not my primary concern.
I know that right now I'm spawning a subprocess and doing things serially. I look forward to your replies.
#!/usr/bin/python
import sys, os
import subprocess
if (len(sys.argv) > 1):
if( sys.argv[1] == 'start' ):
print "starting jboss"
arg = str(sys.argv[1])
elif( sys.argv[1] == 'stop' ):
print "stopping"
elif( sys.argv[1] == 'status' ):
print "getting status"
arg = str(sys.argv[1])
print arg
else:
print "start or stop?"
exit(1)
else:
print "unexpected error"
host = "10.24.14.10 "
command = "sudo /etc/init.d/jbossas " + arg
fullcommand = "ssh " + " " + host + " " + " " + command + " "+ arg
print "full command: ", fullcommand
process = subprocess.Popen(fullcommand, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output
host = "10.24.14.20 "
fullcommand = "ssh " + " " + host + " " + " " + command + " "+ arg
process = subprocess.Popen(fullcommand, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output
host = "10.30.1.1 "
fullcommand = "ssh " + " " + host + " " + " " + command + " "+ arg
process = subprocess.Popen(fullcommand, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output

Categories