面向开发工程师的 ssh 技巧

你不需要一个图形化的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。

很烦对不对,我们看看这些流程中有什么痛点:

  1. 每次连接都要输入密码,重开一个 session 也需要输入密码。烦。
  2. 每次连接 db server 都要先连接 app server,然后再ssh 到 db server。烦。
  3. 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

你可能感兴趣的:(面向开发工程师的 ssh 技巧)