iTerm2 实现 ssh 自动登陆,并使用 Zmodem 实现快速传输文件

原文连接:fuckcloudnative.io/posts/iterm…html

对于 YAML 工程师来讲,咱们常常须要 ssh 登陆不一样的服务器,每次登陆时都要经历两个步骤:linux

  1. 输入 ssh root@host-ip
  2. 输入密码

每次都重复这样的操做,不只麻烦,还要记忆好多东西。对于 Windows 用户来讲,可使用 Xshell 来实现自动登陆功能,macOS 用户就比较麻烦了。iTerm2macOS 平台上最强大的终端工具,虽然默认没有提供自动登陆的功能,但咱们能够尝试经过它提供的其余功能来打造自动登陆的功能。git

固然,既然我写了这篇文章,就说明我已经找到了方法,下面就直接开门见山放干货。我想提醒你的是,我这里提供的方法绝对是你历来没有见过的,你可能会以为网上能搜到不少和我相似的方案,但若是你仔细看就能看出区别来,网上的方案都是不完美的,和其余功能同时使用时会出现莫名其妙的问题(具体是什么问题后面我会讲到),我把这些问题都解决了,获得了一个极其完美的方案。github

本文将提供两种自动登陆方案,首先来看第一种方案。web

1. 经过触发器自动登陆

iTerm2 有一个很是强大的功能叫触发器(Trigger),触发器是用户可配置的正则表达式,当终端会话接收到与正则表达式相匹配的文本时,会执行相关的操做。这里的操做包括突出显示匹配的文本,显示警报,发回文本等等。正则表达式

触发器的一种高级用法是捕获与正则表达式匹配的输出,并在工具栏中显示这些匹配线。 例如,您能够建立一个匹配编译器错误的触发器。 当你运行时,错误会出如今你的窗口一侧,你能够点击每个跳到它的右边。 更多信息可在 Captured Output 手册中找到。shell

本文将利用触发器来实现 ssh 自动登陆的功能。首先点击 Preference -> Profiles,选中你要登陆的服务器,Command 这里填写你的 ssh 登陆的 ip 和用户名,若是端口不是 22 还要指定端口:express

而后点击 Advanced,找到 Trriggers,点击 editbash

在 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/ite…

  • 下载并安装脚本
$ 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 一块儿使用时,会出现一些莫名其妙的问题,本文最后也给出了解决方案。

参考