之前一直使用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程序,就不需要再手動去重新開機了。
真香。