緣由
由於工作需要,我需要大量生成iOS推送服務端所用到的PEM文件,一個個手動生成那真是要煩死。梳理了一下PEM文件的生成過程,發現涉及到證書導出、生成與驗證,這樣的話我還真的只能一個個手動生成。不過仔細研究,還是可以提高生成自動化水平的,比如PEM文件後期生成過程的把P12文件轉換成PEM文件。
這個P12文件轉換成PEM文件的自動化過程有一個難點,就是需要手動輸入密碼,換言之就是有交互的過程,如果寫成腳本,如果讓腳本自動交互呢?也就是把密碼寫死在腳本裡,在腳本執行時自動輸入密碼。還真讓我找到了解決這個問題的神器:expect和autoexpect。
看看Expect的介紹:我們通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對於需要交互的場合則必須通過人工來干預,有時候我們可能會需要實現和交互程序如telnet服務器等進行交互的功能。而expect就使用來實現這種功能的工具。
那麼autoexpect是什麼呢?實際上寫expect腳本仍然是挺煩的,autoexpect是用來錄制生成expect腳本的,這樣就更加自動化了。
實現
Mac本身帶有expect工具,這可以通過expect -v看出來,但是卻沒有autoexpect。其實是因為Mac帶的這個expect比較簡單,用brew install expect就可以安裝上帶autoexpect的expect了。
本文中PEM文件的生成主要參考了《iOS Push 證書的重新生成》 一文,涉及到的自動化對應”把兩個.p12文件轉換成.pem文件”之後的過程.
在Terminal下執行autoexpect -p -f autoGeneratePEM.exp就可以開始腳本的錄制了,錄制成功後,生成的autoGeneratePEM.exp就是你需要的腳本了,稍做修改,就可以使用了。
下面是我錄下來的腳本,由於是錄制的,所以會有一些冗余代碼。
如何使用:
確保cert.p12和key.p12在當前目錄
修改腳本中的custompassword為兩個p12文件的導出密碼(這裡假設兩個是一樣的),以及修改customPemPassPhrase為你自己定義的字符串。
執行腳本時需要bundleid參數,示例:./autoGeneratePEM.exp com.test.123456,或者./autoGeneratePEM.exp 123456
#!/usr/bin/expect -f # # This Expect script was generated by autoexpect on Tue Aug 25 14:39:57 2015 # Expect and autoexpect were both written by Don Libes, NIST. set force_conservative 0 ;# set to 1 to force conservative mode even if ;# script wasn't run conservatively originally if {$force_conservative} { set send_slow {1 .1} proc send {ignore arg} { sleep .1 exp_send -s -- $arg } } set timeout -1 set bundleid [lindex $argv 0] spawn $env(SHELL) match_max 100000 expect -exact "\[?1034hbash-3.2\$ " send -- "openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12" expect -exact "openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12" send -- "\r" expect -exact "Enter Import Password:" send -- "custompassword\r" expect -exact "bash-3.2\$ " send -- "openssl pkcs12 -nocerts -out key.pem -in key.p12" expect -exact "openssl pkcs12 -nocerts -out key.pem -in key.p12" send -- "\r" expect -exact "Enter Import Password:" send -- "custompassword\r" expect -exact "Enter PEM pass phrase:" send -- "customPemPassPhrase\r" expect -exact "Verifying - Enter PEM pass phrase:" send -- "customPemPassPhrase\r" expect -exact "bash-3.2\$ " send -- "openssl rsa -in key.pem -out key.unencrypted.pem" expect -exact "openssl rsa -in key.pem -out key.unencrypted.pem" send -- "\r" expect -exact "Enter pass phrase for key.pem:" send -- "customPemPassPhrase\r" expect -exact "bash-3.2\$ " send -- "cat cert.pem key.unencrypted.pem > $bundleid.pem" expect -exact "cat cert.pem key.unencrypted.pem > $bundleid.pem" send -- "\r" expect -exact "bash-3.2\$ " send -- "exit\r" expect eof
參考:
iOS Push 證書的重新生成 – think12的專欄 – 博客頻道 – CSDN.NET
autoexpect讓expect腳本更加簡單!-lonelysoul011-ChinaUnix博客
Where is the autoexpect command line tool on OSX Mountain Lion (10.8.5) – Ask Different
Apple Push Notification Services in iOS 6 Tutorial: Part 1/2 – Ray Wenderlich
Shell腳本學習之expect命令 – 專注於系統運維,系統架構方向 – 博客頻道 – CSDN.NET