-
Notifications
You must be signed in to change notification settings - Fork 61
/
run_jobs.py
173 lines (134 loc) · 4.31 KB
/
run_jobs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
""" This file allows multiple jobs to be run on a server. After each job, an
email is sent to notify desired people of its completion.
Must specify a text job file that contains the names and commands for each
job. Each job has 4 lines, containing:
1) the name,
2) the command,
3) the location of a file where the job output should be saved,
4) a blank line.
An example job file format is as follows:
Job1
python job.py path1 arg1
path/output1.txt
Job2
python job.py path2 arg2
path/output2.txt
Usage: python run_jobs.py jobs.txt
"""
import os
import sys
import smtplib
import string
from time import time
import helperFuncs as helper
DEFAULT_EMAIL_LIST = ['[email protected]', '[email protected]']
SENDING_ADDRESS = '[email protected]'
MINIMUM_JOB_SECONDS = 600 # 10 minutes
PRINT_LAST_X_LINES = 300
ERROR = 1
SUCCESS = 0
WARNING = 2
def reload_files():
reload(helper)
class Job:
def __init__(self, name, command, output_file):
self.name = name
self.command = command
self.output_file = output_file.rstrip('\n')
def send_email(subject, text, to_addr_list=DEFAULT_EMAIL_LIST):
body = string.join(('From: %s' % SENDING_ADDRESS,
'To: %s' % to_addr_list,
'Subject: %s' % subject,
'',
text), '\r\n')
try:
server = smtplib.SMTP('smtp.gmail.com:587') # NOTE: This is the GMAIL SSL port.
server.ehlo() # this line was not required in a previous working version
server.starttls()
server.login(SENDING_ADDRESS, 'gmail_password')
server.sendmail(SENDING_ADDRESS, to_addr_list, body)
server.quit()
print "Email sent successfully!"
except:
return "Email failed to send!"
def load_job_file(filename):
f = open(filename, 'r')
lines = f.readlines()
jobs = []
i = 0
while i < len(lines):
jobname = lines[i]
command = lines[i+1]
output_file = lines[i+2]
job = Job(jobname, command, output_file)
jobs.append(job)
i = i+4
return jobs
def run_job(job_obj):
""" Runs a system command for a job, returns whether it
succeeded and output text to be emailed.
Inputs:
job_obj: an instance of the Job class
Returns
A code indicating whether the job was successful, and
a string containing text about the job and job output to
be mailed to the user
"""
print "\nRunning job", job_obj.name
if os.path.exists(job_obj.output_file):
message = "The desired output file " + job_obj.output_file + " already exists."
print "Error!", message
return ERROR, message
t0 = time()
# execute the command
stream = os.popen(job_obj.command)
output = stream.read()
# save output to desired file
of = open(job_obj.output_file, 'w')
of.write(output)
of.close()
t1 = time()
total_secs = t1 - t0
hours, mins, secs = helper.get_secs_mins_hours_from_secs(total_secs)
time_str = "Job ended. Total time taken: " + str(int(hours)) + "h " + str(int(mins)) + "m " + str(int(secs)) + "s"
print time_str
if not os.path.exists(job_obj.output_file):
message = "Job failed to create the desired output file."
print "Error!", message
code = ERROR
elif total_secs < MINIMUM_JOB_SECONDS:
message = "The total time taken for the job was suspiciously short."
print "Warning!", message
code = WARNING
else:
message = ""
print "Job finished successfully!"
code = SUCCESS
lines = output.split('\n')
tail = "\n".join(lines[-PRINT_LAST_X_LINES:])
message += "\n\n" + time_str + "\n\n"
message += "The last " + str(PRINT_LAST_X_LINES) + " lines of job output were:\n\n"
message += tail
return code, message
def email_about_job(job_obj, status, output):
if status == ERROR:
title = "Error! Problem with job " + job_obj.name
elif status == SUCCESS:
title = "Success! Job " + job_obj.name + " is finished"
else:
title = "Warning! Job " + job_obj.name + " finished too quickly"
send_email(title, output)
def run_jobs(jobfile):
jobs = load_job_file(filename)
for job in jobs:
status, output = run_job(job)
email_about_job(job, status, output)
send_email("ALL JOBS FINISHED!!", "Congratulations, all of the jobs in the file " + jobfile + " have finished running.")
if __name__ == "__main__":
if len(sys.argv) < 1:
print "Error! Usage is python run_jobs.py jobs.txt"
print "See this file's documentation for required format for jobs.txt"
filename= sys.argv[1]
jobfile=sys.argv[1]
print "Running all jobs in file", jobfile, ". . ."
run_jobs(jobfile)