做一件事,无论大小,倘无恒心,是很不好的。而看一切太难,固然能使人无成,但若看得太容易,也能使事情无结果。
背景
因为负担不起每年都要在阿里云里面购买服务器的支出,于是和网络运营商申请了公网IP,在家搞了个树莓派,于是便可以省下一笔费用。但是我不是申请固定的公网IP,因此每天公网IP都会变化。于是又自己用PHP写了个DDNS,调用阿里云接口(域名是在万网申请的)动态解析新的IP。但依然会有些问题,比如网络运营商有时会把我的公网又改掉,造成我的网站无法访问,直到我自己上去看才发现,有时不够及时发现。于是便想着用程序定时去ping一下,一点ping不通就发邮件通知我。
代码
package main
import (
"crypto/tls"
"fmt"
"github.com/golang-module/carbon"
"io"
"net"
"os"
"time"
"github.com/sirupsen/logrus"
"gopkg.in/gomail.v2"
)
func main() {
// 记录日志
fileName := "./logs/Info_First_" + carbon.Now().Format("Ymd") + ".log"
logFile, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err == nil {
logrus.SetOutput(io.MultiWriter(os.Stdout, logFile))
} else {
logrus.SetOutput(os.Stdout)
logrus.Error(err)
}
CheckServer()
}
// CheckServer ping服务器
func CheckServer() {
// ping通后保存公网IP
remoteAddr := ""
// 是否发送过邮件
isSendFlag := false
// 失败次数
failTimes := 0
for {
// 超过无响应时间则为ping不通
timeout := time.Duration(5 * time.Second)
conn, err := net.DialTimeout("tcp", "****:***", timeout)
if err != nil {
failTimes++
// 连续超过十次判断为ping不通
if failTimes >= 10 {
if !isSendFlag {
err := Send(remoteAddr + " site unreachable,please check the server")
if err != nil {
logrus.Error("send email error", err)
}
isSendFlag = true
}
logrus.Error("Site unreachable, error: ", err)
continue
}
// 失败一次则20s再重新ping一次
time.Sleep(time.Duration(20 * time.Second))
continue
}
// 成功则把失败次数重置
failTimes = 0
remoteAddr = conn.RemoteAddr().String()
isSendFlag = false
fmt.Println("dial success,ip: ", remoteAddr)
time.Sleep(time.Duration(5 * time.Minute))
}
}
func Send(content string) error {
message := `
<p> Hello %s,</p>
<p style="text-indent:2em">%s</p>
`
host := "邮箱的smtp地址"
port := 25
userName := "你的邮箱"
password := "邮箱smtp的密码"
m := gomail.NewMessage()
m.SetHeader("From", userName) // 发件人
m.SetHeader("To", userName) // 收件人
m.SetHeader("Subject", "Warning! Site unreachable!") // 邮件主题
// text/html 的意思是将文件的 content-type 设置为 text/html 的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。
// 可以通过 text/html 处理文本格式进行特殊处理,如换行、缩进、加粗等等
m.SetBody("text/html", fmt.Sprintf(message, "QiuYiEr", content))
d := gomail.NewDialer(
host,
port,
userName,
password,
)
// 关闭SSL协议认证
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil {
return err
}
logrus.Info("email sent")
return nil
}
这也是我从别的博主学来的,特此注明一下:
- golang的ping检测网络实现_github_zwl的博客-CSDN博客_golang ping
- Go使用gomail发送邮件详解,及使用smtp、email发送邮件_吕小布@lawson的博客-CSDN博客_go 发送邮件
下图为收到的邮件