22

在macOS上用supervisor构建稳定的SSH转发

 4 years ago
source link: https://blog.csdn.net/lanphaday/article/details/105463124
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

之前一直使用SSH指定端口转发请求,一直能用,但是很烦。因为每次都要输入密码之类的,而且经常会断开,断开后又输密码,神烦。前几日决心解决这个问题,作为一名Python开发者,首先想到的就是supervisor,最后也证明这个想法行得通。

brew install supervisor 把它安装上,然后运行 brew service start supervisor 运行起来。打开 /usr/local/etc/supervisor.d ,然后在下面建立一个 ssh_d.ini 文件,内容如下:

[program:ssh_d]
command=你的SSH命令
autostart=true
autorestart=true
numprocs=1
killasgroup=true
stopasgroup=true

其中 autostartautorestart 参数能够确保你的SSH进程始终在。然后运行 supervisorctl start ssh_d 把它运行起来。但这一步不一定能够成功,因为你可能没有配置免密码登陆服务器。

ssh-keygen -t rsa 可以为自己生成配对的公钥和密钥,注意保存的文件名,以免和其它服务器的混了,比如我自已输入的是 ssh_d_id_rsa

生成后,把 ssh_d_id_rsa 文件放到 ~/.ssh/ 目录下。用 scpssh_d_id_rsa.pub 上传到你的服务器,并把它加到服务器的 ~/.ssh/authorized_keys 文件中。然后配置本机的 /etc/ssh/ssh_config 文件,加上这么一节:

Host 你的主机IP
    SendEnv LANG LC_*
    IdentityFile ~/.ssh/ssh_d_id_rsa

这时候你再试试 supervisorctl restart ssh_d ,估计就能运行成功了。可以在浏览器里试一下代理,有没有转发请求出去。

以上,基本上使用起来就没有问题了。不过好像时间久了SSH进程会有点不靠谱,具体啥原因也不好深究,我的方案是定时,15分钟,让 supervisor 重启一次SSH进程。

在macOS上做定时任务,一开始我是延用了 crontab ,发现各种折腾,都没有效果。最后靠谱的是 launchd 。具体的操作是先把 supervisor 重启进程的命令写成脚本,比如 ~/supervisorctl_restart_ssh_d.sh ,内容如下:

#!/bin/sh
/usr/local/bin/supervisorctl restart ssh_d

保存后,注意用 chmod +x 给这个脚本文件加上可执行权限,不然就会失败。

下一步是进入 ~/Library/LaunchAgents 目录,然后写一个 ssh_d.crontab.plist 的文件,里面的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>ssh_d.crontab</string>

  <key>ProgramArguments</key>
  <array>
    <string>改成你的supervisorctl_restart_ssh_d.sh文件的绝对路径</string>
  </array>

  <key>StartInterval</key>
  <integer>900</integer>

  <key>RunAtLoad</key>
  <true/>
    <key>StartInterval</key>
  <integer>900</integer>

  <key>RunAtLoad</key>
  <true/>

  <key>Debug</key>
  <true/>

  <key>StandardErrorPath</key>
  <string>/tmp/AlTest1.err</string>

  <key>StandardOutPath</key>
  <string>/tmp/AlTest1.out</string>
</dict>
</plist>

然后运行 launchctl load ssh_d.crontab.plist 装裁这个命令,成功的话,你可以看到你的SSH的进程ID变化了,这就表示它成功重启了SSH进程。

另外也可以用命令来查看任务运行的结果:

launchctl list | grep ssh_d
-	0	ssh_d.crontab

中间的 0 表示运行成功,如果是非 0 值,比如 78,可以使用另一个命令来看看是表示什么意思:

launchctl error 78
78: Function not implemented

至此,SSH进程常用常新,可用性增强了不少。

不过如果合上mac的屏幕,较长时间之后再打开,你会发现SSH连接已经断开,但并不会自动重连。

目前这个痛点还没有好的解决方案。我暂时是用浏览器打开 http://127.0.0.1:9001 页面,这是 supervisor 的Web控制台。然后手动启一下 ssh_d ,因为不需要输入密码,而且这种情况一天也没有几次,尚可接受。

如果你打不开 http://127.0.0.1:9001 ,可以编辑 /usr/local/etc/supervisord.ini 文件,把下面两行前面的注释去除,

[inet_http_server]         ; inet (TCP) server disabled by default
port=127.0.0.1:9001        ; ip_address:port specifier, *:port for all iface

然后再运行 brew service restart supervisor 就可以了。

更新:

一觉醒来,有了灵感:屏幕亮起,也就是由睡眠到唤醒,是一种事件啊。 launchd 应该有机制可以获取这个事件,然后做一些事情的。一搜索,果然有方法。具体就是在 ssh_d.crontab.plist 文件中加入下面这几行:

<key>WatchPaths</key>
  <array>
    <string>/Library/Preferences/SystemConfiguration</string>
  </array>

原理是当唤醒macOS时,这个文件夹(也就是系统配置)会有一些变化,比如WIFI之类的,所以当这个文件夹变化时,就重启一下我们的SSH进程,就不需要再手动去重启了。

真香。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK