2013年9月24日 星期二

寫了一個管理帳號的script

差不多去年這個時候,小弟魯蛇剛接任所上的linux工作站網路管理員。
本來以為是個輕鬆的職位,畢竟先代某陳姓大網管超~級~強~,工作站維護得這麼好,佈線設備也都沒什麼問題,我們應該也只要做點基本維護就好,結果工作其實還頗多(OAO)。
要幫所上的人申請新帳號;幾台伺服器還裝著mandriva 2009,久未更新,很多套件可能都過期了,需要用主流的CentOS或Debian來取代;有的工作站連yum都沒有,只能抓rpm,那時候試著要裝yum,結果遇到瘋狂的相依關係,最後只好放棄;最後還有工作用的軟體跟license server需要維護。

最近為了減輕一些工作,就寫了一個自動加入帳號的script,理論上用bash script應該就做得到,不過考量到其中有許多文字處理,數字比對的部分,最後還是用python的譔寫,雖然說nis主機也是debian 5的老主機,必須用python2.5來譔寫有一點troll,不過還是比用shell快一點。

ps:其實linux工作站使用人數比較少,理論上用vim手動加搞不好比較快,不過當作python練習XDD。

一、帳號記錄文件:

伺服器使用的帳號記錄是nis,內容跟/etc/passwd沒什麼兩樣,類似這樣: account:passwd:uid:gid:comment:homedirectory:shell
這沒什麼好講的,大部分的內容都是預設,比較不一樣的是我們uid, gid設定:為了管理方便,我們的gid是以1k為單位分給一位教授,對應可使用的1000個uid,例如某葉教授(咦)的gid為10000,那uid就從10000-10999,下一位教授就從gid, uid為11000開始。
註:這樣每個教授可以收1000位學生,就算每學期收個20個,也要收50年才行,應該頗夠用吧XD

二、程式規劃:

規畫程式的功能如下。
功能一,加入使用者:
1. 詢問使用者帳號名稱(account)
2. 列出目前可用的gid列表,要求管理者選擇。
3. 查詢目前表列的uid,取得下一個uid值。
4. 請管理者輸入comment。
5. 列出homedirectory資料夾選項。
6. 詢問使用者密碼。
功能二,刪除使用者:
這個比較簡單,把account comment掉就是了。
第二部分,實際操作:
1. 備份檔案,複製一份檔案,儲存為原檔名.日期。
2. 將要加入的內容寫入passwd檔中。
3. 呼叫ypinit -m更新資料庫。
4. 呼叫ypasswd修改密碼檔,這部分用pexpect達成。
5. 產生一份需要建立新資料夾的資料夾位置,到nfs使用。

三、實作:

上述功能看來有點多,其實寫起來滿快的,幾個小時吧。主要是python功能過於OP,大部分慢下來的地方都是我腦殘忘記該怎麼寫,或是為了使用python 2.5以致需要去查語法。
程式大部分是使用python 的list來硬幹,儲存需要寫入的字串,將需要增加的或刪除的資料新增到list之中。

大概沒什麼好講的,唯一值得一提的就是發現python 整合了expect的功能:pexpect,原本呼叫yppasswd的部分想要用expect來寫,但發現用pexpect比較方便,也可以把改密碼的工作交給python去執行,比分出一個expect script還要方便。
跟上一篇的expect講的差不多,pexpect同樣支援spawn, expect, send等基本語法
例如程式中需要設定新加入使用者的密碼:
for key,val in passwddict.iteritems():
    print("change passwd of user %s" % key)
    rootpass = “rootpassword”
    child = pexpect.spawn("yppasswd %s" % key)
    child.expect('password:')
    child.sendline(rootpass)
    child.expect('password:')
    child.sendline(val)
    child.expect('password:')
    child.sendline(val)
    child.expect(pexpect.EOF, timeout=None)
從存好的dictionary裡面取出一對帳號跟密碼,然後去設定passwd,同樣的缺點也是root密碼會曝光,權限要小心設。

PS:剛剛發現暑假過太頹廢,從八月中到現在都沒寫新文,看到同學們都在當助教惹,自己也要努力點才行。

2013年9月20日 星期五

使用Expect進行大量修改密碼

Expect 最近稍微研究了一下expect這個工具,簡單來說,它可以作為使用者對shell的代言人,本來需要大量使用者回應的工作,可以交由expect來處理,主要的資料是參考資料2,瀏覽書還是吸收技術最快的方法。
最簡單的工作,就是由expect來幫我們輸入密碼,例如我們要改帳號,都需要輸入舊密碼和兩次新密碼,如果有1000個帳號要修改時,等於要輸入3000次密碼,如果兩次新密碼打錯的話還會吃屎重來,真是讓人感到絕望…。
再更簡單一點就是管工作站時,要向其他電腦下命令,如果有10台電腦要執行一樣的命令,而且要用su執行?
結果書上還出現用expect來控制gdb的除錯程序,好像有一點猛…

--

expect最基本的指令大概是: spawn, expect, send,有了這三個就能做不少事情惹。 例如我想從工作站上載東西下來:
#!/usr/bin/expect

set password “mypassword”

spawn scp account@workstation:/etc/hosts . 
match_max 1000
expect "*?assword: "
send "$password\r"
expect eof 
首先我們設定password變數,利用spawn叫shell執行scp指令,當scp要求輸入密碼時,由expect承接,scp輸出內容是account@workstation 's password: ,用*整個接下來;用send把內容傳給shell,就完成一個自動下載檔案的程式了。
唯一要注意的大概只有那個\r回車鍵,沒打那個就相當於打完password後沒按enter,你會看到程式停在螢幕上對你微笑,等你按enter。

上面只是個簡單的例子,回應很單純,不過稍微擴展一下,我們就可以完成一個自動改nis密碼的script
#!/usr/bin/expect

set rootpwd "wwww"
set newpwd [lindex $argv 1]

spawn yppasswd [lindex $argv 0]
expect "*?root password:"
send "$rootpwd\r"
expect "*?new password:"
send "$newpwd\r"
expect "*?new password:"
send "$newpwd\r"
expect eof

使用./script account newpasswd,即可自動修改密碼,只要事先把account跟newpasswd打好,一瞬間密碼就改完了,有幾千人都不用怕。雖一的缺點大概是要把root password明文寫在script裡面,這個script一定要保護好,用root擁有然後權限設成700吧。

參考資料:
1. expect man page
2. http://it-ebooks.info/book/2189/