背景
開發服務器放在公司內網,但需要從外網可以隨意訪問。而公司是通過撥號,因此IP不能固定。
傳統的做法是:在路由器上將DDNS帳號密碼填上去,然後就可以不管了。但這需要DDNS服務提供商,一般大型靠譜的DNS服務商卻不支持DDNS服務。
我們公司的DNS是託管在dnspod上的,他們的域名更新速度快,還可以對訪問線路做解析優化,在目前網通電信不通暢的情況下還是很有用的,唯一遺憾的是沒有對DDNS的支持。
解決方案
但是有一點希望的是:DNSPod提供了DNS操作API,所以,可以通過API變相實現DDNS,只是需要自己寫點代碼就搞定了。
思路是:
通過corn週期性的(每分鐘)執行一個程序,此程序通過外部網站獲取自己的外網ip,然後跟自己存儲下來的前一個IP比較,如果變了則更新DNS,否則不操作。
之所以這麼做,是因爲服務商不允許頻繁做更新DNS的操作。
實現
#!/bin/sh
#每次IP變動都將追加寫入到這個文件中
IPFILE=/tmp/ipNow
#通過ifconfig.me網站檢測自己的公網IP
#ip=`curl -s 'http://checkip.dyndns.org' | sed 's/.*Current IP Address: \([0-9\.]*\).*/\1/g'`
ip=`curl -s 'ifconfig.me'`
echo `date +%FT%T` "ip now:$ip"
#update ip record file
if [ -e $IPFILE ]; then
echo "ip:$ip"
#取得最後一個IP
ipOld=`cat $IPFILE | tail -n 1 | awk '{print $1}'`
echo "cat IPFILE:$ipOld"
if [ -n "$ip" ]; then
#注意下面的測試條件,一定要對變量$ip用雙引號包起來,以防$ip爲空時導致語法錯誤
if [[ "$ip" != $ipOld ]]; then
echo "$ip `date +%FT%T`" >> "$IPFILE"
echo "ip is different with the last time!"
#update DDNS
re=`curl -X POST https://dnsapi.cn/Record.Ddns -d "[email protected]&login_password=xxx&format=json&domain_id=7483437&record_id=35656076&sub_domain=dev&value=$ip&record_line=默認"`
echo $re >> /var/log/updateDDNS.log;
else
echo "ip not change
";
fi;
fi;
else
echo $ip >> "$IPFILE"
fi
技巧
檢測IP
如果想要檢測是否爲一個IP地址,可以使用如下方法做正則表達式判斷:
if [[ $ip =~ ([0-9]{2}.?){4} ]]; then echo 'yes'; else echo 'no'; fi
注意上面的'=~'操作符,表示右邊是一個正則表達式。特別需要說明的是:
- 表達式沒有引號;
- 沒有像其它語言中使用斜線將整個表達式包裹起來。
shell 對條件測試方法
有3種:test關鍵字;單層方括號'[ arg ... ]'; 雙層方括號'[[ expression ]];
前兩者是同義詞,只是語法不一樣。雙層方括號功能更強大,除能實現test關鍵字相同的功能外,還可以測試複雜表達式,並支持'&&', '||', '!' 邏輯組合, 以及正則表達式(使用'=~'操作符)。