iTerm2 實現 ssh 自動登入,並使用 Zmodem 實現快速傳輸檔案

米開朗基楊發表於2021-01-18

原文連結:https://fuckcloudnative.io/posts/iterm2-auto-login/

對於 YAML 工程師來說,我們經常需要 ssh 登入不同的伺服器,每次登入時都要經歷兩個步驟:

  1. 輸入 ssh root@host-ip
  2. 輸入密碼

每次都重複這樣的操作,不僅麻煩,還要記憶好多東西。對於 Windows 使用者來說,可以使用 Xshell 來實現自動登入功能,macOS 使用者就比較麻煩了。iTerm2macOS 平臺上最強大的終端工具,雖然預設沒有提供自動登入的功能,但我們可以嘗試通過它提供的其他功能來打造自動登入的功能。

當然,既然我寫了這篇文章,就說明我已經找到了方法,下面就直接開門見山放乾貨。我想提醒你的是,我這裡提供的方法絕對是你從來沒有見過的,你可能會覺得網上能搜到很多和我類似的方案,但如果你仔細看就能看出區別來,網上的方案都是不完美的,和其他功能同時使用時會出現莫名其妙的問題(具體是什麼問題後面我會講到),我把這些問題都解決了,得到了一個極其完美的方案。

本文將提供兩種自動登入方案,首先來看第一種方案。

1. 通過觸發器自動登入

iTerm2 有一個非常強大的功能叫觸發器(Trigger),觸發器是使用者可配置的正規表示式,當終端會話接收到與正規表示式相匹配的文字時,會執行相關的操作。這裡的操作包括突出顯示匹配的文字,顯示警報,發回文字等等。

觸發器的一種高階用法是捕獲與正規表示式匹配的輸出,並在工具欄中顯示這些匹配線。 例如,您可以建立一個匹配編譯器錯誤的觸發器。 當你執行時,錯誤會出現在你的視窗一側,你可以點選每一個跳到它的右邊。 更多資訊可在 Captured Output 手冊中找到。

本文將利用觸發器來實現 ssh 自動登入的功能。首先點選 Preference -> Profiles,選中你要登入的伺服器,Command 這裡填寫你的 ssh 登入的 ip 和使用者名稱,如果埠不是 22 還要指定埠:

然後點選 Advanced,找到 Trriggers,點選 edit

在 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 等這些單詞了:

到這一步算是完美解決了自動登入的需求。但還是有一點小瑕疵,每臺伺服器的觸發器正規表示式都是不一樣的,如果你要登入的伺服器很多,這個工作量將非常大,要不要用這種方法可以自己取捨。

下面我將介紹另外一種方案,相比之前的方案,下面的方案需要編寫指令碼,但它是可複用的,每臺伺服器都可以使用同一個指令碼。如果你要登入的伺服器數量很多,相比之下之前的方案工作量更大。

2. 通過 expect 自動登入

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 將變成徹底完美的方案,觸發器的方案就可以拋之腦後了。

下面我將詳細介紹 expectlrzsz 一起使用的問題,及其解決方案。

3. 使用 Zmodem 實現快速傳輸檔案

很多時候我們需要在本機和遠端伺服器間進行檔案傳輸,通常都是使用 scp 命令進行傳輸,但其實通過 Zmodem 傳輸起來更方便。

什麼是 Zmodem

Zmodem 是針對 modem 的一種支援錯誤校驗的檔案傳輸協議。ZmodemYmodem 的改進版,後者又是 Xmodem 的改進版。Zmodem 不僅能傳輸更大的資料,而且錯誤率更小。

利用 Zmodem 協議,可以在 modem 上傳送 512 位元組的資料塊。Zmodem 包含一種名為檢查點重啟的特性,如果通訊連結在資料傳輸過程中中斷,能從斷點處而不是從開始處恢復傳輸。

配置 iTerm2 支援 Zmodem

要讓 iTerm2 在遠端伺服器上支援通過 Zmodem 協議傳輸,需要分別在服務端和客戶端進行相應配置。網上大多數文件都只提到客戶端部分。因為收發方都必須有支援 Zmodem 協議的工具,才能進行正常收發。下面我們就來看看是如何進行配置的:

服務端配置

lrzsz 軟體包是 支援 Zmodem 協議的工具包。 其包含的 rzsz 命令是通過 ZModem 協議在遠端伺服器和終端機器間上傳下載檔案的利器。

為了正確通過 szrz 命令傳輸檔案,服務端需要安裝 lrzsz 軟體包的。

  • Ubuntu 或 Debian
$ apt-get install lrzsz
  • RHEL 或 CentOS
$ yum install lrzsz

客戶端配置

和伺服器端一樣,客戶端同樣需要安裝 lrzsz 軟體包。這裡通過 Homebrew 進行 lrzsz 軟體包安裝:

$ brew install lrzsz

配置 iTerm2

在全球最大同性交友網站 Github 上,已經有人共享了一個叫 “ZModem integration for iTerm 2” 的專案。我們只需下載其相應指令碼,並進行簡單配置就可以很容易的在 iTerm2 上實現對 Zmodem 的支援。

專案地址:https://github.com/kuoruan/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 上的觸發器

開啟 iTerm2 ,點選 PreferencesProfiles 選擇指定的 Profile。然後繼續選擇 AdvancedTriggers,並點選 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 根據終端上顯示的字元通過指定的觸發器呼叫相應的傳送和接收指令碼。

使用 Zmodem 傳輸檔案

傳送檔案到遠端伺服器

  • 在遠端伺服器執行 rz 命令
  • 本地選擇檔案傳輸
  • 等待傳輸指示消失

接收遠端伺服器的檔案

  • 在遠端伺服器執行 sz filename1 filename2 … filenameN 命令
  • 本地選擇目錄儲存
  • 等待傳輸指示消失

Zmodem 與 expect 結合

如果你真的按照我提供的步驟操作了,最後你會發現根本無法傳輸檔案。其實這個問題不在於 Zmodem 本身,而是 expect 的問題,如果你將 ProfileCommand 換成 ssh root@host 這種形式,就可以正常傳輸檔案了。

難道 expect 真的就沒有辦法了嗎?那之前的工作豈不是都化為烏有了?別慌,不但有辦法,而且這個辦法非常簡單,簡單的讓你想笑。只需要在 Profile 的 Command 命令前面加上一句 export LC_CTYPE=en_US 就行了:

收工!

4. 總結

本文詳細介紹了 macOS 平臺中的 iTerm2 如何使用觸發器和 expect 來實現 ssh 自動登入遠端伺服器,以及如何在 macOS 下通過 Zmodem快速傳輸檔案。當 expect 和 Zmodem 一起使用時,會出現一些莫名其妙的問題,本文最後也給出瞭解決方案。

參考


Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12離線安裝包釋出地址http://store.lameleg.com ,歡迎體驗。 使用了最新的sealos v3.3.6版本。 作了主機名解析配置優化,lvscare 掛載/lib/module解決開機啟動ipvs載入問題, 修復lvscare社群netlink與3.10核心不相容問題,sealos生成百年證書等特性。更多特性 https://github.com/fanux/sealos 。歡迎掃描下方的二維碼加入釘釘群 ,釘釘群已經整合sealos的機器人實時可以看到sealos的動態。

相關文章