L
Lorenzo
I have this script that I want to use weekly to send me email with
information regarding disk space and available upgrades for my system.
This script is actually a learning tool for me as I learn Python. The
problem I've run into has me stumped and I need some help. What happens
is when the script runs it does these things, parses the result and
appends that to an html string:
1) checks disk space by using df -t reiserfs
2) runs time emerge --sync
3) runs emerge -uvp world
4) runs emerge -uv --fetchonly world
The 'emerge' command is a Gentoo specific one. If I remove step 3),
everything else runs just fine, the email is sent and I receive what I
expect. But when step 3) is allowed to run, even if its the only command
that runs, it hangs somewhere in the function getCommandOutput. If I try
and debug the command, it appears to hang on this line:
err = child.wait()
I suspect a race condition, but I'm not sure how to proceed, can someone
lend me a hand. Here is the script I wrote, I got the command
getCommandOutput from this site:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52296
TIA
information regarding disk space and available upgrades for my system.
This script is actually a learning tool for me as I learn Python. The
problem I've run into has me stumped and I need some help. What happens
is when the script runs it does these things, parses the result and
appends that to an html string:
1) checks disk space by using df -t reiserfs
2) runs time emerge --sync
3) runs emerge -uvp world
4) runs emerge -uv --fetchonly world
The 'emerge' command is a Gentoo specific one. If I remove step 3),
everything else runs just fine, the email is sent and I receive what I
expect. But when step 3) is allowed to run, even if its the only command
that runs, it hangs somewhere in the function getCommandOutput. If I try
and debug the command, it appears to hang on this line:
err = child.wait()
I suspect a race condition, but I'm not sure how to proceed, can someone
lend me a hand. Here is the script I wrote, I got the command
getCommandOutput from this site:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52296
TIA
Code:
#!/usr/bin/python
################################
### NEED TO RUN THIS AS ROOT ###
### EMERGE SYNC REQUIRES THIS ###
################################
import os, re, smtplib, MimeWriter, mimetools, cStringIO, popen2, fcntl,
select, pdb
cmd = 'df -t reiserfs'
finalList = []
theOutput = []
text = "This realy should be in HTML"
html = "<html>\
<head>\
<meta http-equiv=\"Content-Type\" content=\"text/html;
charset=iso-8859-1\">\
</head>\
<BODY><BR><font color='green'><em>Disk Utilization on
Hedley:</em></font><BR>"
out = cStringIO.StringIO()
writer = MimeWriter.MimeWriter(out)
txtin = cStringIO.StringIO(text)
def createhtmlmail (html, text, subject):
"""Create a mime-message that will render HTML in popular
MUAs, text in better ones"""
import MimeWriter
import mimetools
import cStringIO
out = cStringIO.StringIO() # output buffer for our message
htmlin = cStringIO.StringIO(html)
txtin = cStringIO.StringIO(text)
writer = MimeWriter.MimeWriter(out)
#
# set up some basic headers... we put subject here
# because smtplib.sendmail expects it to be in the
# message body
#
writer.addheader("Subject", subject)
writer.addheader("MIME-Version", "1.0")
writer.addheader("From", "[email protected]")
writer.addheader("To", "[email protected]")
#
# start the multipart section of the message
# multipart/alternative seems to work better
# on some MUAs than multipart/mixed
#
writer.startmultipartbody("alternative")
writer.flushheaders()
#
# the plain text section
#
subpart = writer.nextpart()
subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
pout = subpart.startbody("text/plain", [("charset", 'us-ascii')])
mimetools.encode(txtin, pout, 'quoted-printable')
txtin.close()
#
# start the html subpart of the message
#
subpart = writer.nextpart()
subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
#
# returns us a file-ish object we can write to
#
pout = subpart.startbody("text/html", [("charset", 'us-ascii')])
mimetools.encode(htmlin, pout, 'quoted-printable')
htmlin.close()
#
# Now that we're done, close our writer and
# return the message body
#
writer.lastpart()
msg = out.getvalue()
out.close()
print msg
return msg
def makeNonBlocking(fd):
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
try:
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)
except AttributeError:
fcntl.fcntl(fd, fcntl.F_SETFL, fl | fcntl.FNDELAY)
def getCommandOutput(command):
theOutput = []
child = popen2.Popen3(command, 1) # capture stdout and stderr from
command
child.tochild.close() # don't need to talk to child
outfile = child.fromchild
outfd = outfile.fileno()
errfile = child.childerr
errfd = errfile.fileno()
makeNonBlocking(outfd) # don't deadlock!
makeNonBlocking(errfd)
outdata = errdata = ''
outeof = erreof = 0
while 1:
ready = select.select([outfd,errfd],[],[]) # wait for input
if outfd in ready[0]:
outchunk = outfile.read()
if outchunk == '': outeof = 1
outdata = outdata + outchunk
if errfd in ready[0]:
errchunk = errfile.read()
if errchunk == '': erreof = 1
errdata = errdata + errchunk
if outeof and erreof: break
select.select([],[],[],.1) # give a little time for buffers to fill
err = child.wait()
if err != 0:
raise RuntimeError, '%s failed w/ exit code %d\n%s' % (command, err,
errdata)
theOutput.append(outdata)
theOutput.append(errdata)
return theOutput
#Run df and get the disk info
output = os.popen(cmd)
# match two or more spaces, the header line has a sngle
# space between the 'Mouted on' field
# We need to keep those together
# The other spaces are the separation in the field headers
# To get the output from df down to just the field headers
# and the data, we need to match 2 or more spaces
# -1 eliminates the \n at the end of output.
# We'll get it back when we write each line to the
# mail message, I suspect
html += "<font color='blue'>"
for lines in output.readlines():
p = re.compile('\ +')
formattedText = p.subn(' ', lines[:-1], 5)
html += formattedText[0] + '<BR>'
html += "</font>"
mydata = getCommandOutput("time emerge --sync")
p = re.compile('\ +')
p.subn(' ', mydata[1])[0]
p = re.compile('\n')
string = (p.subn('<BR>', mydata[1]))[0]
html += "<BR><BR><em><font color='green'>Sync Time: " + "<BR>" +
"</font></em>" + "<font color='blue'>" + string + "</font>"
mydata = ""
mydata = getCommandOutput("emerge -uvp world")
p = re.compile('\ +')
(p.subn(' ', mydata[0]))[0]
p = re.compile('\n')
html += "<font color='blue'>" + (p.subn('<BR>', mydata[0]))[0] +
"</font>"
try:
getCommandOutput('emerge -uv --fetchonly world')
html += "<font color='Green'><em><BR>Fetch completed
successfuly!</em></font>"
except RuntimeError:
html += "< font color='Red'><BR>******Fetch did not complete
successfully!*********</font>"
html+= '</BODY> </HTML>'
out = cStringIO.StringIO()
writer = MimeWriter.MimeWriter(out)
txtin = cStringIO.StringIO("This should be in HTML")
subject = "Emerge info and disk utilization on Hedley"
message = createhtmlmail(html, text, subject)
server = smtplib.SMTP("hedley")
server.sendmail('[email protected]', '[email protected]', message)
server.quit()