原文連接:fuckcloudnative.io/posts/iterm…html
對於 YAML 工程師來講,咱們常常須要 ssh 登陸不一樣的服務器,每次登陸時都要經歷兩個步驟:linux
ssh root@host-ip
每次都重複這樣的操做,不只麻煩,還要記憶好多東西。對於 Windows
用戶來講,可使用 Xshell
來實現自動登陸功能,macOS 用戶就比較麻煩了。iTerm2
是 macOS
平臺上最強大的終端工具,雖然默認沒有提供自動登陸的功能,但咱們能夠嘗試經過它提供的其餘功能來打造自動登陸的功能。git
固然,既然我寫了這篇文章,就說明我已經找到了方法,下面就直接開門見山放乾貨。我想提醒你的是,我這裏提供的方法絕對是你歷來沒有見過的,你可能會以爲網上能搜到不少和我相似的方案,但若是你仔細看就能看出區別來,網上的方案都是不完美的,和其餘功能同時使用時會出現莫名其妙的問題(具體是什麼問題後面我會講到),我把這些問題都解決了,獲得了一個極其完美的方案。github
本文將提供兩種自動登陸方案,首先來看第一種方案。web
iTerm2 有一個很是強大的功能叫觸發器(Trigger),觸發器是用戶可配置的正則表達式,當終端會話接收到與正則表達式相匹配的文本時,會執行相關的操做。這裏的操做包括突出顯示匹配的文本,顯示警報,發回文本等等。正則表達式
觸發器的一種高級用法是捕獲與正則表達式匹配的輸出,並在工具欄中顯示這些匹配線。 例如,您能夠建立一個匹配編譯器錯誤的觸發器。 當你運行時,錯誤會出如今你的窗口一側,你能夠點擊每個跳到它的右邊。 更多信息可在 Captured Output 手冊中找到。shell
本文將利用觸發器來實現 ssh 自動登陸的功能。首先點擊 Preference -> Profiles
,選中你要登陸的服務器,Command
這裏填寫你的 ssh 登陸的 ip 和用戶名,若是端口不是 22 還要指定端口:express
而後點擊 Advanced
,找到 Trriggers,點擊 edit
:bash
在 Regular Eexpression 中,填寫你要匹配的正則表達式。因爲這裏是要在看到 password
的提示後輸入密碼,因此這裏填寫 password
,若是你服務器的密碼提示是 passwd
,你要改爲匹配這個正則,固然還有些服務器提示的是 Password
,因此咱們能夠用正則 (p|P)ass(word|wd):
所有匹配。在 Action
中選擇 Send Text
,在 Parameters
中填寫你的密碼,最後增長一個 \r
字符。\r
是回車,這就至關於你輸入了密碼,並按了下回車。最後,要把 Instant
的複選框選中。服務器
我這裏多加了一個正則表達式,由於第一次登陸服務器時會提示 Are you sure you want to continue connecting (yes/no)?
。
如今在你的終端會話中雙指輕按觸控板,或者鼠標右擊,就能夠選擇你的 Profile 自動登陸了:
到了這一步尚未結束,這個方法看似完美,實際上是有問題的。假設你在這臺服務器上再經過 ssh 去登陸其餘服務器,仍然會觸發 Triggers;再假設其餘服務器的密碼和這臺服務器的密碼是不一樣的,這時候就會陷入尷尬的境地,無論你嘗試多少次,觸發器都會自動輸入以前設置的密碼,你將永遠登陸不上另外一臺服務器。
還有一些其餘的問題,好比你在終端中輸入的任何命令只要匹配了觸發器的正則,就會自動輸入密碼,使用體驗很是很差:
解決這個問題其實也很簡單,只須要提升正則匹配的準確度就好了,直接看圖:
如今再經過 ssh 登陸其餘服務器,觸發器不再會自動輸入密碼了:
在終端中輸入的命令也不會匹配到 password 和 Password 等這些單詞了:
到這一步算是完美解決了自動登陸的需求。但仍是有一點小瑕疵,每臺服務器的觸發器正則表達式都是不同的,若是你要登陸的服務器不少,這個工做量將很是大,要不要用這種方法能夠本身取捨。
下面我將介紹另一種方案,相比以前的方案,下面的方案須要編寫腳本,但它是可複用的,每臺服務器均可以使用同一個腳本。若是你要登陸的服務器數量不少,相比之下以前的方案工做量更大。
expect 是一個自動化交互套件,主要應用於執行命令和程序時,系統以交互形式要求輸入指定字符串,實現交互通訊。它的自動交互流程以下:
spawn
啓動指定進程 ---> expect
獲取指定關鍵字 ---> send
向指定程序發送指定字符 ---> 執行完成退出
接下來咱們將利用 expect 來實現 ssh 自動登陸。首先新建一個文件 /usr/local/bin/iterm2Login.sh
,內容以下:
#!/usr/bin/expect
set timeout 30
set host [lindex $argv 0]
# 這一行是設置一個變量的意思,變量名隨便起,儘可能有意義,後面表示的是傳入的參數,0 表示第一個參數,後面會用到。
set port [lindex $argv 1]
set user [lindex $argv 2]
set pswd [lindex $argv 3]
spawn ssh -p $port $user@$host
# spawn 是 expect 環境的內部命令,它主要的功能是給 ssh 運行進程加個殼,用來傳遞交互指令。
expect {
"(yes/no)?"
{send "yes\n";exp_continue;}
-re "(p|P)ass(word|wd):"
{send "$pswd\n"}
}
# expect 也是 expect 環境的一個內部命令,用來判斷上一個指令輸入以後的獲得輸出結果是否包含 "" 雙引號裏的字符串,-re 表示經過正則來匹配。
# 若是是第一次登陸,會出現 "yes/no" 的字符串,就發送(send)指令 "yes\r",而後繼續(exp_continue)。
interact
# interact:執行完成後保持交互狀態,把控制權交給控制檯。
複製代碼
argv 0
, argv 1
, argv 2
, argv 3
三個參數依次爲 ip、端口號、用戶名、密碼。
賦予腳本執行權限:
$ sudo chmod +x /usr/local/bin/iterm2Login.sh
複製代碼
將 Profile 中的 Command 部分替換成經過上面的腳原本登陸:
最後將觸發器中的全部規則都刪掉,只留下一個:
大功告成!
看來這個方法比上面的方法更加完美,由於 expect
只針對當前登陸的服務器,後續再經過當前服務器 ssh 登陸其餘服務器,不會再自動輸入密碼什麼的。若是服務器數量不少,也不用再一個一個去改觸發器規則,簡直太爽了。
固然,expect 也會遇到一些問題,好比沒法正常使用 lrzsz
,而這些問題在使用觸發器時是不存在的。固然,這些問題是能夠解決的,解決以後,expect 將變成完全完美的方案,觸發器的方案就能夠拋之腦後了。
下面我將詳細介紹 expect
和 lrzsz
一塊兒使用的問題,及其解決方案。
不少時候咱們須要在本機和遠端服務器間進行文件傳輸,一般都是使用 scp
命令進行傳輸,但其實經過 Zmodem
傳輸起來更方便。
Zmodem
是針對 modem
的一種支持錯誤校驗的文件傳輸協議。Zmodem
是 Ymodem
的改進版,後者又是 Xmodem
的改進版。Zmodem
不只能傳輸更大的數據,並且錯誤率更小。
利用 Zmodem
協議,能夠在 modem
上發送 512 字節的數據塊。Zmodem
包含一種名爲檢查點重啓的特性,若是通訊連接在數據傳輸過程當中中斷,能從斷點處而不是從開始處恢復傳輸。
要讓 iTerm2
在遠端服務器上支持經過 Zmodem
協議傳輸,須要分別在服務端和客戶端進行相應配置。網上大多數文檔都只提到客戶端部分。由於收發方都必須有支持 Zmodem
協議的工具,才能進行正常收發。下面咱們就來看看是如何進行配置的:
lrzsz
軟件包是 支持 Zmodem
協議的工具包。 其包含的 rz
、sz
命令是經過 ZModem
協議在遠程服務器和終端機器間上傳下載文件的利器。
爲了正確經過 sz
、rz
命令傳輸文件,服務端須要安裝 lrzsz
軟件包的。
$ apt-get install lrzsz
複製代碼
$ yum install lrzsz
複製代碼
和服務器端同樣,客戶端一樣須要安裝 lrzsz
軟件包。這裏經過 Homebrew
進行 lrzsz
軟件包安裝:
$ brew install lrzsz
複製代碼
在全球最大同性交友網站 Github
上,已經有人共享了一個叫 「ZModem integration for iTerm 2」 的項目。咱們只需下載其相應腳本,並進行簡單配置就能夠很容易的在 iTerm2
上實現對 Zmodem
的支持。
$ wget -qO /usr/local/bin/iterm2-zmodem.sh https://github.com/kuoruan/iterm2-zmodem/raw/master/iterm2-zmodem.sh
$ chmod +x /usr/local/bin/iterm2-zmodem.sh
複製代碼
打開 iTerm2
,點擊 Preferences
→ Profiles
選擇指定的 Profile
。而後繼續選擇 Advanced
→ Triggers
,並點擊 Edit
添加兩個觸發器。
按以下內容添加兩個觸發器,首先增長 sz
指令的觸發器:
Regular expression: rz waiting to receive.\*\*B0100
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-zmodem.sh send
Instant: checked
複製代碼
其次增長 rz
指令的觸發器:
Regular expression: \*\*B00000000000000
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-zmodem.sh recv
Instant: checked
複製代碼
成功增長完成後的效果,相似下圖:
配置這兩個觸發器的做用就是讓 iTerm2
根據終端上顯示的字符經過指定的觸發器調用相應的發送和接收腳本。
rz
命令sz filename1 filename2 … filenameN
命令若是你真的按照我提供的步驟操做了,最後你會發現根本沒法傳輸文件。其實這個問題不在於 Zmodem
自己,而是 expect 的問題,若是你將 Profile
的 Command
換成 ssh root@host
這種形式,就能夠正常傳輸文件了。
難道 expect 真的就沒有辦法了嗎?那以前的工做豈不是都化爲烏有了?別慌,不但有辦法,並且這個辦法很是簡單,簡單的讓你想笑。只須要在 Profile 的 Command 命令前面加上一句 export LC_CTYPE=en_US
就好了:
收工!
本文詳細介紹了 macOS 平臺中的 iTerm2
如何使用觸發器和 expect
來實現 ssh 自動登陸遠程服務器,以及如何在 macOS
下經過 Zmodem
快速傳輸文件。當 expect 和 Zmodem 一塊兒使用時,會出現一些莫名其妙的問題,本文最後也給出瞭解決方案。