天天看點

在macOS上用supervisor建構穩定的SSH轉發

之前一直使用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
           

其中

autostart

autorestart

參數能夠確定你的SSH程序始終在。然後運作

supervisorctl start ssh_d

把它運作起來。但這一步不一定能夠成功,因為你可能沒有配置免密碼登陸伺服器。

ssh-keygen -t rsa

可以為自己生成配對的公鑰和密鑰,注意儲存的檔案名,以免和其它伺服器的混了,比如我自已輸入的是

ssh_d_id_rsa

生成後,把

ssh_d_id_rsa

檔案放到

~/.ssh/

目錄下。用

scp

ssh_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程序,就不需要再手動去重新開機了。

真香。

繼續閱讀