runem這個小程式,主要是因為,通常我RF的電磁模擬要花上很多的時間,丟上工作站的話都要跑很久,如果是在windows下透過putty連結工作站,要是putty突然當掉,導致跑到一半的模擬中止掉就頭大了。
面對這個狀況有幾個解決方案,例如使用專面負責離線工作的程式,像是screen;但因為幾台工作站的作業系統太過老舊,上面甚至連screen都沒有;另一個解決方案是用atd,也就是linux內建的服務,在某個時間進行某個指令,這個解決方式很好,只是at 的語法比較麻煩,強迫每個使用者去記也沒什麼道理,身為網管要提供使用者方便,決定把at包成一個shell,使用者只要使用這個指令即可。
--
其實這個只要用shell script寫幾行即可,不過考量到一些特別的功能,還是用python來寫。 核心功能其實就一個,透過python 的subprocess把em 的指令透過atd送進去(ref 3):
cmd = "echo 'em -v {0}'".format(filename)
cmd2 = "at now +0 minutes"
p1 = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
p2 = subprocess.Popen(cmd2, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=p1.stdout)
監控程序:
啟動atd之後,必須要監控該執行程序,看看它是不是結束了,這裡我使用強者我同學AZ的python 解決方案: pnotify(ref 2)
當然,這個監控的程式也要用atd的方式來執行。
第一步是先找出atd呼叫出來的em -v的process,再來的function就是抄襲AZ的,簡單來說是先檢查/proc,看看該pid是否開啟,然後每隔一段時間就用kill 0的方式檢查該程序存在與否。
找出pid的部分,用的方法就笨一點,直接叫外部的ps,抓出有em的部分、濾出該使用者的資訊、排除grep自身,再用pid排個序,抓最大(最新)的pid即可,這個方法在pid用完一圈後會出錯,不過將就用一下,之後再看看有沒有更好的解,有的話麻煩強者們提示一下m(_ _)m:
pid_list = []
cmd = "sleep 1; ps -elf"
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
stdout = p.stdout.read().decode("utf-8").split('\n')
for line in stdout:
if ("em -v" in line) and (username in line) and ("grep" not in line):
pid_list.append(line.split()[3])
就可以抓出pid了。
再來再用atd開啟一個pnotify的監控工作即可。
email:
為了方便使用者,使用的是python + SMTP module,這部分的程式碼只能用明碼寫出帳號密碼,不過這在權限上設定為只有我能看即可;主要code如下:
# open smtp session
session = smtplib.SMTP('smtp.gmail.com', 587)
session.ehlo
session.starttls()
session.ehlo
session.login(account, password)
# prepare the send message
msg = MIMEText("Your EM simulation: {0} is over".format(filename))
msg['Subject'] = "the test title"
msg['From'] = sender
msg['To'] = receiver
# send the message
session.sendmail(sender, [receiver], msg.as_string())
session.quit()
透過google的smtp進行文件的轉送,其實這沒什麼,大部分都是抄的lol(ref 1)
成果:
現在工作站可以透過
runem file1.son 的方式執行一個超大em模擬,em模擬結束時候,可以透過電子郵件,通知進行模擬的使用者。
本程式透過python譔寫,相當快速,總開發時間約3-4天。
原始碼已上傳到github上:
https://github.com/lc85301/runem
附章:
趁著這次佈署runem的時候,順便佈署了另一個小script: clearcdslck
其實沒什麼,只是一個shell包含一行指令:
find . -name *.cdslck -exec rm -fv {} \;
方便使用者清除因不當結束產生的.cdslck檔。
參考資料:
1. about python mail using google SMTP
http://segfault.in/2010/12/sending-gmail-from-python/
2. about pnotify.py
http://blog.azhuang.me/2011/07/script-for-notifying-process.html#more
3. about python subprocess
http://docs.python.org/2/library/subprocess.html
致謝:
本文感謝AZ Huang同學的pnotify.py以及在SMTP使用上的指導,另外感謝同實驗室的曾奕恩大師幫忙測試本程式。