博客

  • CentOS 8 安装 VPN pptp服务

    CentOS 8 安装 VPN pptp服务

    安装前检查系统

     # cat /etc/redhat-release
    CentOS Linux release 8.0.1905 (Core)
    

    是否支持PPTP

     # modprobe ppp-compress-18 && echo support
    support
    

    是否开启TUN/TAP

     # ls /dev/net/tun && echo support
    /dev/net/tun
    support
    

    是否开启ppp

     # ls /dev/ppp && echo support
    /dev/ppp
    support
    

    如果环境不满足上面3个条件,表示很可能不支持pptp。

    安装 PPP

    #  yum install ppp ppp-devel pptp net-tools iptables
    

    安装 PPTPD

    下载 pptpd-1.4.0.tar.gz

    https://sourceforge.net/projects/poptop/files/pptpd/pptpd-1.4.0/

     # wget https://jaist.dl.sourceforge.net/project/poptop/pptpd/pptpd-1.4.0/pptpd-1.4.0.tar.gz
     # tar zxvf pptpd-1.4.0.tar.gz
     # ./configure --prefix=/usr/local/pptpd
     # make && make install
    
     # mkdir -p /usr/lib/pptpd/
     # ln -s /usr/local/pptpd/lib/pptpd/pptpd-logwtmp.so /usr/lib/pptpd/pptpd-logwtmp.so
    

    手动链接下 pptpd-logwtmp.so
    由于 CentOS 8 还没有 pptpd rpm 包, 所以这里手动编译安装, 如果您些麻烦,我这里手动打了 centos 8 pptpd rpm 包

     # rpm -ivh https://pic.ithothub.com/wp-content/uploads/2020/03/pptpd-1.4.0-2.el8.x86_64.rpm
    

    配置 PPTPD

    /etc/ppp/options.pptpd

     # cat /etc/ppp/options.pptpd
    name pptpd
    refuse-pap
    refuse-chap
    refuse-mschap
    require-mschap-v2
    require-mppe-128
    proxyarp
    lock
    nobsdcomp
    novj
    novjccomp
    nologfd
    idle 2592000
    ms-dns 8.8.8.8
    ms-dns 8.8.4.4
    

    /etc/ppp/chap-secrets

     # cat /etc/ppp/chap-secrets
    # Secrets for authentication using CHAP
    # client    server  secret          IP addresses
    aikaiyuan pptpd 123456 *
    

    client server secret IP addresses
    用户名: aikaiyuan 密码: 123456 允许所有IP

    /etc/pptpd.conf

     # cat /etc/pptpd.conf
    option /etc/ppp/options.pptpd
    logwtmp
    localip 192.168.9.1
    remoteip 192.168.9.11-30
    

    localip: VPN网关地址
    remoteip: 分配给客户端IP地址范围

    启动PPTPD

     # /usr/local/pptpd/sbin/pptpd -d -c /etc/pptpd.conf
    
        1  8387  8387  8387 ?           -1 Ss       0   0:00 /usr/local/pptpd/sbin/pptpd -d -c /etc/pptpd.conf
     8387 10718  8387  8387 ?           -1 S        0   0:00  \_ pptpd [10.10.10.22:63A0 - 0080]
    10718 10719  8387  8387 ?           -1 S        0   0:00      \_ /usr/sbin/pppd local file /etc/ppp/options.pptpd 115200 192.168.9.1:192.168.9.11 ipparam 10.10.10.22 plugin /usr/lib/pptpd/pptpd-logwtmp.so pptpd-original-ip 10.10.10.22 remotenumber 10.10.10.22
    

    客户端 10.10.10.22 以成功链接

    开启NAT

    开启路由转发

     # echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/50-forward.conf
     # sysctl -p
     # sysctl net.ipv4.ip_forward
    net.ipv4.ip_forward = 1
    

    开启NAT转换

     # /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 192.168.9.0/24 -j MASQUERADE
     # /sbin/iptables -I INPUT -p tcp -m tcp --dport 1723 -j ACCEPT
    

    这里eth0是我的 公网接口
    1723 是 PPTP默认 端口

    转载请注明:爱开源 » CentOS 8 安装 VPN pptp服务

  • 常用开源许可证有啥区别

    常用开源许可证有啥区别

    电脑中的软件都有License,开源软件也不例外。不过开源软件的开源许可证那么多种,又都有什么区别呢?让我们上网搜搜看。

    定义

    下面是摘录百度百科的定义:

    license是版权许可证。相当于软件版权。软件版权属于知识产权的著作权范畴,具有知识产权的特征,即时间性,专有性和地域性。软件版权在法律上称为“计算机软件著作权”。属于著作权(知识产权)的一种。国家颁布有《计算机软件保护条例》,保护权益人的软件著作权。

    自由软件/开源软件是自由的,免费的,源代码开放的,我们可自由下载安装和使用。同时,为了维护作者和贡献者的合法权利,保证这些软件不被一些商业机构或个人窃取,影响软件的发展,开源社区开发出了各种的开源许可协议。

    我们常用的开源软件协议大致有GPL、BSD、MIT、Mozilla、Apache和LGPL。

    如何选择

    先看看网上搜索的第一张表格

    很详细是不是,不过还有一个更直观的。国内有个阮一峰汉化了乌克兰程序员Paul Bagwell的分析图

    第三张图是英文的,比上图清晰点,

    结束语

    笔者刚开始接触开源的时候,对开源协议了解一知半解,只晓得不要钱就能用,却没有发现他们之间是有区别的。特意从网上搜集了上面的三张图,希望能帮助到和我一样情况的朋友。

    转载:https://www.linuxprobe.com/how-choice-license.html

    转载请注明:爱开源 » 常用开源许可证有啥区别

  • pam_limits(sshd:session):could not sent limit for ‘nofile’

    ssh 无法登陆, 日志如下

    pam_limits(sshd:session):could not sent limit for 'nofile'
    

    原因是因为, /etc/security/limits.conf nofile 大于 fs.nr_open

     # cat /etc/security/limits.conf | grep nofile
    * soft nofile 65535
    * hard nofile 65535
    
     # sysctl -a | grep fs.nr_open
    fs.nr_open = 65500
    

    调整 fs.nr_open 即可

     # sysctl -w fs.nr_open=655000
    

    转载请注明:爱开源 » pam_limits(sshd:session):could not sent limit for ‘nofile’

  • htaccess 常用案例

    htaccess 常用案例

    不同域名 指向不同目录

    RewriteEngine On
    RewriteBase /
    
    ## ========    aaa123.aikaiyuan.com    ==========
    RewriteCond %{HTTP_HOST} ^aaa123.aikaiyuan.com$ [NC]
    RewriteCond %{REQUEST_URI} !^/aaa123/
    RewriteRule ^(.*)$ aaa123/$1?Rewrite [L,QSA]
    
    ## ========    bbb321.aikaiyuan.cn    ==========
    RewriteCond %{HTTP_HOST} ^bbb321.aikaiyuan.cn$ [NC]
    RewriteCond %{REQUEST_URI} !^/bbb321/
    RewriteRule ^(.*)$ bbb321/$1?Rewrite [L,QSA]
    

    css,js文件 301 跳转

    RewriteCond %{REQUEST_URI} ^.*(.css|.js)$
    RewriteRule ^/data1/www/htdocs/258/aikaiyuan/1(.*) https://pic.aikaiyuan.com$1  [L,QSA,R=301] [L]
    

    添加 Header 响应头

    <FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|cur|bmp)$">
    Header set Cache-Control "max-age=2592000"
    Header set Aikaiyuan "HIT"
    </FilesMatch>
    
    # curl -s -I https://www.aikaiyuan.com/wp-content/uploads/2019/11/htaccess.jpg
    HTTP/2 200
    server: nginx
    date: Fri, 22 Nov 2019 09:40:32 GMT
    content-type: image/jpeg
    content-length: 44491
    last-modified: Fri, 22 Nov 2019 09:40:03 GMT
    accept-ranges: bytes
    cache-control: max-age=2592000
    via: 10035
    aikaiyuan: HIT
    

    添加 expire 响应头

    <IfModule mod_expires.c>
    ExpiresActive On
    
    ExpiresByType text/css A2592000
    ExpiresByType application/javascript A2592000
    
    ExpiresByType image/* A2592000
    
    ExpiresByType application/x-gzip A86400
    ExpiresByType application/zip A86400
    ExpiresByType application/x-rar-compressed A86400
    
    ExpiresDefault A600
    </IfModule>
    
    # curl -s -I https://www.aikaiyuan.com/wp-content/uploads/2019/11/htaccess.jpg
    HTTP/2 200
    server: nginx
    date: Fri, 22 Nov 2019 09:42:59 GMT
    content-type: image/jpeg
    content-length: 44491
    last-modified: Fri, 22 Nov 2019 09:40:03 GMT
    accept-ranges: bytes
    cache-control: max-age=2592000
    expires: Sun, 22 Dec 2019 09:42:59 GMT
    via: 10035
    aikaiyuan: HIT
    
    RewriteRule wp-content/.*/[^/]*(responsive|css|js|dynamic|loader|fonts)\.php - [E=cache-control:max-age=3600]
    

    禁止某些 IP 访问

    order deny,allow
    deny from 1.1.1.1   # 1.1.1.1/32
    deny from 1.1.1     # 1.1.1.0/24
    deny from 1.1       # 1.1.0.0/16
    deny from 1         # 1.0.0.0/8
    

    返回 403 错误

    禁止某些 User-Agent 访问

    SetEnvIfNoCase User-Agent "Mozilla/5.0 \(Windows NT 6.1; WOW64; rv:7.0.1\) Gecko/20100101 Firefox/7.0.1" bad_ua
    SetEnvIfNoCase User-Agent "Apache-HttpClient" bad_ah
    SetEnvIfNoCase User-Agent "scrapy.org" bad_scrapy
    
    order deny,allow
    deny from env=bad_ua
    deny from env=bad_ah
    deny from env=bad_scrapy
    

    只要包含 就返回 403 错误
    注意: 特殊符号转移
    测试: curl -A “scrapy.org” https://www.aikaiyuan.com/

    禁止某些 URL 访问

    SetEnvIf Request_URI /xmlrpc.php deny_xmlrpc
    order deny,allow
    Deny from env=deny_xmlrpc
    

    返回 403 错误

    禁止某些 目录 访问

    SetEnvIf Request_URI "test/" deny_dir
    Order deny,allow
    Deny from env=deny_dir
    

    返回 403 错误

    http 调整到 https

    RewriteEngine on
    RewriteCond %{HTTP:X-FORWARDED-PROTO} !^https$
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=307]
    

    将所有的请求转发到index.php处理

    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^.*$ /index.php [L,QSA]
    
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ public/index.php [L]
    

    将/aa/路径的请求转发到aa目录下的index.php处理,其他转到根目录下的index.php处理

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} ^/aa/
    RewriteRule ^aa/(.*)$ aa/index.php/$1 [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/aa/
    RewriteRule ^(.*)$ index.php/$1 [L]
    

    相关文章

    转载请注明:爱开源 » htaccess 常用案例

  • Chrome 79 地址栏显示 https://www

    Chrome 79 地址栏显示 https://www

    最近 Google Chrome 发布最新版本 Chrome 79 https://chromereleases.googleblog.com/2019/12/stable-channel-update-for-desktop.html

    升级完成之后发现, 地址栏 $scheme://www 又隐藏了, 很不习惯, 第一感觉我到底访问的是 www.aikaiyuan.com 还是 aikaiyuan.com

    旧版本

    Chrome 79 之前版本, 可以通过 chrome://flags, 禁用 2 参数即可

    • Omnibox UI Hide Steay-State URL Scheme and Trivial Subdomains
    • Omnibox UI Hide Steady-State URL Scheme

    新版本

    Chrome 79 已经不支持 chrome://flags 方式了, 这里使用 插件 方法, 安装 Suspicious Site Reporter , 如果您有更好的方法, 请留言

    安装 Suspicious Site Reporter 插件后, 即可显示 https://www

    插件: Suspicious-Site-Reporter-v1.21

    转载请注明:爱开源 » Chrome 79 地址栏显示 https://www

  • Docker删除镜像错误 image has dependent child images

    Docker删除镜像错误 image has dependent child images

    清理镜像

     # docker images | grep ubuntu
    REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
    ubuntu                                           18.04               775349758637        5 weeks ago         64.2MB
    ubuntu                                           <none>              cf0f3ca922e0        7 weeks ago         64.2MB
    

    由于 ubuntu:18.04 更新了所以, image id 也改变了, \ 可以删除

    # docker rmi cf0f3ca922e0
    Error response from daemon: conflict: unable to delete cf0f3ca922e0 (cannot be forced) - image has dependent child images
    

    意思有其他image在引用, 无法删除

    强制镜像

    # docker rmi -f cf0f3ca922e0
    Error response from daemon: conflict: unable to delete cf0f3ca922e0 (cannot be forced) - image has dependent child images
    

    不推荐, 但这里也失败了

    清理容器后在删除

     # docker ps -a --format "{{.ID}} {{.Status}}" | grep -v ' Up ' | awk '{print $1}' | xargs docker rm
     # docker rmi cf0f3ca922e0
    Error response from daemon: conflict: unable to delete cf0f3ca922e0 (cannot be forced) - image has dependent child images
    

    删除所有非 Up 状态容器, 但最后还是 失败了

    清理依赖镜像

    最主要是找到 有那些 image引用了 cf0f3ca922e0 把引用image清理掉就可以了

     # docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q --filter since=cf0f3ca922e0)
    [registry.docker.io/aikaiyuan/builder:xxxx] sha256:xxx sha256:xxx
    [registry.docker.io/aikaiyuan/builder:yyyy] sha256:yyy sha256:yyy
    ......
    ......
    

    删除 registry.docker.io/aikaiyuan/builder:xxxx, registry.docker.io/aikaiyuan/builder:yyyy 后, cf0f3ca922e0 也就可以正产删除了

    补充

    有效的 none 镜像

    Docker文件系统的组成,docker镜像是由很多 layers组成的,每个 layer之间有父子关系,所有的docker文件系统层默认都存储在/var/lib/docker/graph目录下,docker称之为图层数据库。

    最后做一个总结< none>:< none> 镜像是一种中间镜像,我们可以使用docker images -a来看到,他们不会造成硬盘空间占用的问题(因为这是镜像的父层,必须存在的),但是会给我们的判断带来迷惑。

    无效的 none 镜像

    另一种类型的 < none>:< none> 镜像是dangling images ,这种类型会造成磁盘空间占用问题。

    像Java和Golang这种编程语言都有一个内存区,这个内存区不会关联任何的代码。这些语言的垃圾回收系统优先回收这块区域的空间,将他返回给堆内存,所以这块内存区对于之后的内存分配是有用的

    docker的悬挂(dangling)文件系统与上面的原理类似,他是没有被使用到的并且不会关联任何镜像,因此我们需要一种机制去清理这些悬空镜像。

    我们在上文已经提到了有效的< none>镜像,他们是一种中间层,那无效的< none>镜像又是怎么出现的?这些 dangling镜像主要是我们触发 docker build 和 docker pull命令产生的。

    使用下面的命令可以清理
    docker rmi $(docker images -f “dangling=true” -q)
    docker没有自动垃圾回收处理机制,未来可能会有这方面的改进,但是目前我们只能这样手动清理(写个脚本就好)。

    转载请注明:爱开源 » Docker删除镜像错误 image has dependent child images

  • telnet/nc 操作 memcache

    telnet/nc 操作 memcache

    请求命令格式

    <Command name> <key> <flags> <exptime> <bytes>\r\n
    <data block> \r\n
    

    • \:可以是add,set,replace等
    • \:为memcache key键的名称,要求唯一
    • \:是一个16位的无符号整数(10进制),该标志和需要存储的数据一起存储,并在客户端get数据时返回。客户可以将此标志用做特殊用途,此标志对服务器来说是透明的。
    • \:过期的时间,单位为秒,设置为0表示永不过期。
    • \:需要存储的字节数(不包含最后的“\r\n ”),可以为0,表示空数据。
    • \r\n:命令结尾标识符,在telnet界面输入命令时按回车键即可。
    • \:表示存储的数据内容,即value。

    命令响应

    • Stored 表示存储成功
    • not_stored:表示存储失败(命令正确,但操作不对)
    • Error:表示命令错误

    telnet

    nc

    1)存储数据:printf "set key 0 10 6\r\nresult\r\n" | nc 127.0.0.1 11211
    2)获取数据:printf "get key\r\n" | nc 127.0.0.1 11211
    3)删除数据:printf "delete key\r\n" | nc 127.0.0.1 11211
    4)查看状态:printf "stats\r\n" | nc 127.0.0.1 11211
    

    转载请注明:爱开源 » telnet/nc 操作 memcache

  • time 命令

    如果要选 Linux 下最容易被忽视的命令,time 应该算一个。简单来说,它是一个用来计算命令运行时间的工具,之所以说它容易被忽视,一方面很多人根本不知道 time 的存在,而是习惯在命令启动前后记录两个时间戳,然后手动计算命令运行时间;另一方面很多人虽然知道 time 的存在,但是却并没有真正理解它的含义。

    下面让我们通过若干例子来理解 time 的真正含义:

     # time ls
    
    real    0m0.003s
    user    0m0.001s
    sys     0m0.002s
    

    大概意思是 ls 命令运行花了 0.003 秒,其中用户态花了 0.001 秒,内核态花了 0.002 秒,看上去似乎「real = user + sys」?此等式是否成立,在回答这个问题之前我们不妨看看 real、user、sys 的确切含义,如下定义源自 Stackoverflow:

    • Real is wall clock time – time from start to finish of the call. This is all elapsed time including time slices used by other processes and time the process spends blocked (for example if it is waiting for I/O to complete).
    • User is the amount of CPU time spent in user-mode code (outside the kernel) within the process. This is only actual CPU time used in executing the process. Other processes and time the process spends blocked do not count towards this figure.
    • Sys is the amount of CPU time spent in the kernel within the process. This means executing CPU time spent in system calls within the kernel, as opposed to library code, which is still running in user-space. Like ‘user’, this is only CPU time used by the process.

    总的来说,real 是我们直观感受到的消耗的时间,如果命令运行时被堵塞了,那么堵塞时间也是被统计在内的, user 统计在用户态态模式下消耗的 CPU 时间,如果命令运行时被堵塞了,那么堵塞时间并不被统计在内,sys 统计在内核态模式下消耗的 CPU 时间,如果命令运行时被堵塞了,那么堵塞时间并不被统计在内。

    看上去是否统计堵塞时间是区分 real 和 user、sys 的关键,看看下面这个 sleep 例子:

     # time sleep 2
    
    real    0m2.003s
    user    0m0.001s
    sys     0m0.002s
    

    那么除了堵塞时间,还有别的关键点么,让我们再看看下面两个例子:

     # time find /etc -type f | xargs -n1 -I{} cat {} > /dev/null
    
    real    0m6.315s
    user    0m0.691s
    sys     0m2.030s
    
     # time find /etc -type f | xargs -n1 -I{} -P2 cat {} > /dev/null
    
    real    0m2.327s
    user    0m0.574s
    sys     0m1.678s
    

    前后两个例子的区别在于后者在使用 xargs 的时候通过「-P」选项激活了多进程,换句话说,后者可以同时用到多个 CPU。

    了解了相关知识之后,我们通过 real、user、sys 的大小就可以判断程序的行为:

    • 如果 real 远远大于 user + sys,那么说明程序可能有严重的堵塞问题。
    • 如果 real 基本等于 user + sys,那么说明程序可能没有用到多 CPU 能力,
    • 如果 real 远远小于 user + sys,那么说明程序可能用到了多 CPU 能力。

    怎么样?看似简单的 time 命令,是不是远比你想的要复杂得多!

    https://blog.huoding.com/2019/12/08/788

    转载请注明:爱开源 » time 命令

  • sshmenu

    sshmenu

    如果你还在使用 iTerm, alias 管理 服务器, 可以试试下面 sshmenu

    安装 sshmenu

    # git clone https://github.com/selboo/sshmenu.git
    # cd sshmenu
    # python setup.py install
    

    /root/sshmenu.json

     # cat /root/sshmenu.json
    {
        "targets": [
            {
                "host": "selboo@192.168.1.100",
                "command": "/bin/ssh",
                "friendly": "pi",
                "options": [
                    "-p60777",
                    "-i/root/.ssh/selboo_id_rsa",
                    "-F/root/env/ssh/config",
                    "-oStrictHostKeyChecking=no",
                    "-oConnectTimeout=3"
                ]
            },
            {
                "host": "aikaiyuan@www.aikaiyuan.com",
                "command": "/bin/ssh.sh",
                "friendly": "vps usa",
                "options": [
                    "password123",
                    "-oStrictHostKeyChecking=no",
                    "-oConnectTimeout=3"
                ]
            },
            {
                "host": "root@192.168.199.100",
                "command": "/bin/ssh.sh",
                "friendly": "pi 4B",
                "options": [
                    "mima321",
                    "-oStrictHostKeyChecking=no",
                    "-oConnectTimeout=3"
                ]
            },
            {
                "host": "root@1.1.1.200",
                "command": "/bin/ssh.sh",
                "friendly": "test server",
                "options": [
                    "1234567890",
                    "-p65500",
                    "-oTCPKeepAlive=yes",
                    "-oStrictHostKeyChecking=no",
                    "-oServerAliveInterval=30",
                    "-oConnectTimeout=3"
                ]
            }
        ]
    }
    
    • host: [user]@[host|ip]
    • command: /bin/ssh or /bin/ssh.sh
    • friendly: 备注
    • options:
    1. 第一行是密码
    2. -p: 端口
    3. -oTCPKeepAlive=yes : 保持回话
    4. -oStrictHostKeyChecking=no 不检查known_hosts
    5. -oServerAliveInterval=30 : 保持回话
    6. -oConnectTimeout=3: 连接超时
    7. 更多配置可以 man ssh

    /bin/ssh.sh

    #!/usr/bin/expect
    
    set timeout 20
    
    set cmd [lrange $argv 1 end]
    set password [lindex $argv 0]
    
    eval spawn "ssh $cmd"
    sleep 1
    expect "(yes/no)?" {
        send "yes\r"
        expect "*assword:"
        send "$password\r";
    } "*assword:" {
        send "$password\r";
    } "*assword: " {
        send "$password\r";
    } "*assword:" {
        send "$password\r";
    } "# " {
        send "";
    } "$ " {
        send "";
    }
    
    interact
    

    /root/env/ssh/config

    Host *
        ControlMaster auto
        ControlPath /tmp/%r@%h
        ControlPersist 86400
    

    重用 SSH 连接

    启动

    # alias myssh="sshmenu -c /root/sshmenu.json"
    # myssh
    Select a target (press "h" for help)
        ID User                        | Host                        | Note                        | Login
     ->  1 selboo                      | 192.168.1.100               | pi                          | No
         2 aikaiyuan                   | www.aikaiyuan.com           | vps usa                     | No
         3 root                        | 192.168.199.100             | pi 4B                       | No
         4 root                        | 1.1.1.200                   | test server                 | No
    

    转载请注明:爱开源 » sshmenu

  • 重用 SSH 连接

    重用 SSH 连接

    平时需要经常用到 SSH,比如登录远程服务器,用 Git 推送和更新代码等。建立一次 SSH 连接可能并不需要多久长时间,但是如果要频繁登录同一台服务器,就未免显得有些繁琐和浪费时间。如果是用用户名和密码登录,每次都要输入密码就更加让人崩溃。还有使用 Git 的时候,短时间内可能需要经常 git pull 和 git push,如果每次操作都需要重新建立连接,等待过程就让人心生厌恶了。

    实际上,SSH 有个的特性可以做到重用连接,只有在第一次登录的时候会创建新的连接,后续的会话都可以重用这个已经存在的连接。这样,后续的登录就会非常快,而且不需要输入密码认证。配置也很简单,直接上代码。

    修改 ~/.ssh/config 文件,添加如下配置:

    Host *
        ControlMaster auto
        ControlPath /tmp/ssh_mux_%h_%p_%r
        ControlPersist 86400
    

    意思也很好理解:

    • Host 这一行表示下面这些配置和规则影响到的 host, 表示所有的远程 host 都生效。如果要指定某个(些)特定的 host,可以使用类似 Host *.example.com 的配置。
    • ControlMaster auto 这个选项告诉 SSH 客户端尝试重用现有的连接(master connection)。
    • ControlPath 指定了这个连接的 socket 保存的路径,这里配置的是在 /tmp 目录,实际上可以在任何有读写权限的路径下。/tmp/sshmux%h%p%r 配置了 socket 文件名,%h 表示远程主机名(host),%p 表示远程 SSH 服务器的端口(port),%r 表示登录的远程用户名(remote user name)。这些 socket 可以随时删掉(rm),删除后首次会话又会创建新的 master 连接。曾经遇到过这种情况,本地断网了,打开的几个远程终端都卡死,网络恢复后也一直这样,甚至打开新的终端也登录不上。这个时候只需要把之前的 socket 文件都删掉,重新登录就可以了。
    • ControlPersist 这个选项比较重要,表示在创建首个连接(master connection)的会话退出后,master 连接仍然在后台保留,以便其他复用该连接的会话不会出现问题。这个特性在使用 Git 的时候就非常有用,在频繁提交和拉代码的时候,每次 SSH 会话都是很短暂的,如果 master 连接能保持在后台,后续的操作就会如丝般顺滑。

    只需要添加上面几行配置,SSH 的体验就瞬间上升了好几个档次,简直是懒人必备。

    转载请注明:爱开源 » 重用 SSH 连接