iTerm2 實現 ssh 自動登錄,並使用 Zmodem 實現快速傳輸文件

原文鏈接://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 的支持。

項目地址://github.com/kuoruan/iterm2-zmodem

  • 下載並安裝腳本
$ wget -qO /usr/local/bin/iterm2-zmodem.sh //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離線安裝包發佈地址//store.lameleg.com ,歡迎體驗。 使用了最新的sealos v3.3.6版本。 作了主機名解析配置優化,lvscare 掛載/lib/module解決開機啟動ipvs加載問題, 修復lvscare社區netlink與3.10內核不兼容問題,sealos生成百年證書等特性。更多特性 //github.com/fanux/sealos 。歡迎掃描下方的二維碼加入釘釘群 ,釘釘群已經集成sealos的機械人實時可以看到sealos的動態。

Tags: