2013年7月8日 星期一

使用python執行EM模擬及寄信通知

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使用上的指導,另外感謝同實驗室的曾奕恩大師幫忙測試本程式。

沒有留言:

張貼留言