你不需要一个图形化的ssh客户端
这篇不是 ssh 入门教程,我不会告诉你 ssh 怎么装,配置文件在哪,而且讲解也不会特别细致。
如果你对教程内容感兴趣,可以自己去 baidu 相关内容,哦不,不要用baidu,还是用 bing 吧。
作为一个开发工程师,在你的职业生涯里无论如何避免不了和服务器打交道,尤其是 Linux。你无论如何都需要一个好用的 ssh 客户端。
你是否曾经苦苦寻觅一个好用的图形 ssh 客户端,但是你找到了吗?我估计没有,因为市面上根本就没有一个好用的图形化的 ssh 客户端。不管是商业产品,还是开源产品,一个能打的都没有。需求不复杂的情况,还勉强可以用用,一旦有个稍微高级的需求就抓瞎了。
但是,我们真的需要一个图形化的 ssh 客户端吗?不,不需要。那,不用 xshell ,不用 putty,那用啥?我建议你试试命令行版本的 ssh。也许你只是不大喜欢那些黑漆漆,丑哈哈的窗口,没关系,当你真正体会到命令行的强大,你也许就不会在意他的外表了。
我们来设计一个简单的场景,看看 ssh 能帮我们做什么。
假设,你在 aliyun 上有两台服务器,一台 app,一台 db,但是只有一个公网ip,现在你要连db 服务器,通常会怎么做?先 ssh 到 app server,然后再 ssh 到 db server。中间你可能会输入两次密码。如果密码比较复杂,你可能要切换到一个编辑器,从你的密码文件中复制一下密码。
如果你要拷贝一个文件到 db server,也需要先拷到 app server 上,然后 登上 app server,再把文件拷贝到 db server。
很烦对不对,我们看看这些流程中有什么痛点:
- 每次连接都要输入密码,重开一个 session 也需要输入密码。烦。
- 每次连接 db server 都要先连接 app server,然后再ssh 到 db server。烦。
- mysql 命令行太难用。烦。要是能用本机的mysql 开发工具直接连数据库就好了。
下面我们看看如何解决这些问题。
免密登录
输密码?不存在的,ssh 支持免密登录。你不需要每次都到密码文件里复制粘贴。
你需要使用 ssh-genkey 生成一组 key,然后使用 ssh-copy-id 将公钥传到目标服务器上。配置好之后再连接服务器就不需要输入密码了。 ssh 的时候,你可以使用 -i 参数指定私钥的位置,也可以通过配置文件进行设置:
host app-server
hostname 47.28.xx.xx
IdentityFile ~/.ssh/key
说明
-
host: ip,hostname,或者自定义的名称
if(配置中没有 hostname 设置){ 使用 host 的值作为 ip 或 主机名进行连接 } else { 使用 hostname 的值作为 ip 或 主机名进行连接 此时,host 只是一个逻辑名称,用来区分不同主机的配置 }
hostname: 设定真实的 ip 或 主机名
ProxyJump:设置 ssh 中转服务器
IdentityFile:设置 key 路径
Port:设置连接端口
连接复用
有些时候,即便配置了免密登录,连服务器还是很慢,怎么办?除了优化 ssh server 的配置,你还可以使用ssh 的连接复用功能。
ssh 支持连接复用,也就是说,只要你连上服务器,想再开一个 session 的时候,可以复用之前的连接,而不用创建一个新的连接,这样新开 session 基本可以秒开。但是这时候用命令行参数就比较麻烦了,最好是在 ssh 的配置文件里进行设置。例如:
ControlMaster auto
ControlPersist yes
ControlPath /tmp/ssh.%h:%p.%r
ControlPath 用来设置复用连接的 socket 文件的路径。都是临时文件,连接断掉这些文件会自动删除。放到一个你觉得合适的路径即可。
JUMP!JUMP!JUMP!
目标服务器无法直接连接,这种情况非常常见。这时候我们需要通过其他服务器进行中转,这些用来中转的服务器通常被称作“跳板机”。 ssh 本身就支持通过跳板机连接服务器。
ssh -J Jump-Server1 Target-Server
你不需要手动一个一个的登录服务器。我们的场景中你可以这样登录db server:
ssh -J app-server db-server
如果需要通过多个跳板机连接服务器也不是问题,使用多个 -J 即可,但是要注意先后顺序
ssh -J Jump-Server1 -J Jump-Server2 -J Jump-Server... Target-Server
而且,只要沿途的服务器上都有你的key,一条命令就可以让你直达目标服务器。哪个图形化的客户端能实现这样的功能?即便能,会比一条命令更加优雅吗?
同样,JUMP 也可以在配置文件中进行设置:
host jump-server1
hostname 47.28.xx.xx
...
host jump-server2
hostname 192.168.xx.xx
ProxyJump jump-server1
...
host db-server
hostname 172.30.xx.xx
ProxyJump jump-server2
...
然后就可以通过 ssh db-server 直接连接了
隧道-端口映射
隧道很难理解对吧,那“端口映射”听上去是不是熟悉一些?我们可以通过 ssh 把服务器上的任意端口映射到自己的机器上,比如:mysql。端口映射好之后,随便你用什么工具连数据库都可以。命令的格式是这样的:
ssh -NfL [本地IP:]本地端口:服务ip:服务端口 server
举个例子:我要把远程的 mysql 映射到本机:
ssh -NfL 6666:127.0.0.1:3306 db-server
这里的 127.0.0.1 是指服务器上的 127 而不是你机器上那个 127
这里有一个技巧,要映射的端口不必在目标服务器上,只要目标服务器能访问到就可以映射。上面这条命令可以等价的改写成:
ssh -NfL 6666:172.30.xx.xx:3306 jump-server2
看到两条命令的不同了吗?
除了可以把服务器上的端口映射到本机,也可以把本机的端口映射到服务器上!!不常用,这里就不介绍了
隧道-socks
除了做端口映射,ssh 还可以用来创建 socks 代理。socks 代理能干啥?通常是配置在浏览器里,让你的浏览器可以访问服务器上的 web 服务。
ssh -NfD 本地端口 目标服务器
例如:
ssh -NfD 10000 app-server
然后,你可以在浏览器上使用 127.0.0.1:10000 作为 socks 代理,就可以访问 app server 上的web 服务了。
文件传输
scp 和 sftp 这两个工具,都是用来传输文件的。而且会随着 ssh 一起被安装。虽然两者的操作方式不太相同,但我认为最大的不同可能是 sftp 支持断点续传。
scp 和 sftp 都受益于上面介绍的免密、连接复用、jump、隧道等技术,可以实现免密,免中转,直接与目标服务器进行文件交换。
脚本化
命令好长,记不住啊!是的,的确是记不住,但是也不需要记啊。绝大多数的命令行参数都可以写在配置文件里,如果懒到连ip也不想输(跟我一样)。。。
你写代码的时候遇到一大段需要复用的代码通常会怎么办?当然,复制粘贴是可以的,但是正常人通常会写个类写个函数啥的,把它封装一下对吧?
那。。。当然是把复杂的命令写成脚本啦。
不会写脚本咋办?不难的,你可以把每一个命令及其参数的组合看成是一个 API,脚本也无非是调用几个API 而已。不是不会,只是不熟而已。
你可以把前面的 ssh 命令放在一个叫做 dbserver.sh 的脚本中(随便什么名字),然后加个可执行权限,再把脚本放在 $PATH 路径上。你就可以在任何目录里很方便的登录服务器,或者创建隧道了。不需要记 ip,不需要查密码。
可编程
ssh 除了可以让你交互式的操作服务器以外,还可以进行非交互式操作。例如,你想看下服务器上的时间,你不需要登录到服务器:
# ssh 目标服务器 命令
ssh db-server date
命令行真正强大的地方是可编程。如果你想让 xshell 执行一些批量操作,怎么弄?没法弄!但是命令行可以。
jenkins 都用过吧,如果你只是要完成一些简单的部署任务,你不需要搭一个jenkins 。几行脚本就能搞定
#!/bin/bash
cd 工程目录
# 打包
mvn package 或者 yarn ...
# 部署
scp package remote-server:/path/to/projects
# 重启服务
ssh remote-server restart service
看见了?我们的 jenkins 不也就干了这点儿事吗?无非有个 web 界面,大家可以一起用而已。
如何获得 ssh
- win10 已经自带了 openssh,但是默认可能没有安装
- 如果希望获得更加完整的 Unix like 使用体验,win10 用户可以考虑 WSL2
- 如果你不喜欢 WSL2,又或者是一个顽固的 Win7 支持者,可以考虑 cmder、ConEmu 等第三方的终端模拟器
- 甚至是 git-bash 也是可以的。
不同方式安装的 ssh,其配置文件的路径可能不大一样。
总结
图形化的软件可以让你相对容易上手,如果只是简单用用,是非常好的选择。
但是这些软件同时也限制了你的想象力。高级的事情做不了,自动化的事情做不了。你现在用 xshell,明天不能用了怎么办,或者又出了个更牛的 xxxxshell,你是不是要重新学习一下呢?但是命令行不一样,除非你有一天不需要和服务器打交道了,我保证在你有限的生命里,ssh 命令会一直在那里,他的行为不会改变,配置方式不会改变,你也不需要重新学习。
附录
最后,给一个相对完整的配置文件示例:
# 全局配置
Host *
ControlPath /tmp/ssh.%h:%p.%r
ControlMaster auto
ControlPersist yes
UserKnownHostsFile /dev/null
GlobalKnownHostsFile /dev/null
StrictHostKeyChecking no
AddKeysToAgent yes
PubkeyAcceptedKeyTypes +ssh-dss
ForwardAgent yes
# 保持连接
TCPKeepAlive yes
#ServerAliveCountMax 300
ServerAliveInterval 30
ForwardX11 yes
ForwardX11Trusted yes
CheckHostIP no
Compression yes
IPQos lowdelay
LogLevel QUIET
# server group 1
Host sg1.*
IdentityFile ~/.ssh/zkzy
user root
Host sg1.172.16.103.11
port 5811
hostname 192.168.80.100
Host sg1.172.16.103.* !sg1.172.16.103.11
ProxyJump sg1.172.16.103.11
Host sg1.172.16.103.12
Hostname 172.16.103.12
Host sg1.172.16.103.13
Hostname 172.16.103.13