稳定v1.0.0版本
This commit is contained in:
parent
b4383c9240
commit
e97e8c903a
156
dutiesnet.go
Normal file
156
dutiesnet.go
Normal file
|
@ -0,0 +1,156 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DutiesNet 保证PPPoe可行
|
||||
type DutiesNet struct {
|
||||
PW *PingWorker
|
||||
|
||||
NetProtectTime int64 // 当前时间大于保护时间,才能进行重启的计算操作(pppoe最大重启保护时间, 保证重启后不会重复接受重启命令而造成不停重启 )
|
||||
MaxProtectTime int64 // NetProtectTime保护时间的最大值
|
||||
CmdRestart int64 // 只要大于MaxRestart就重启
|
||||
MaxRestart int64 // 达到这个值就重启
|
||||
}
|
||||
|
||||
// Default 设置默认值
|
||||
func (duties *DutiesNet) Default(pw *PingWorker) {
|
||||
duties.PW = pw
|
||||
atomic.StoreInt64(&duties.MaxProtectTime, 15)
|
||||
atomic.StoreInt64(&duties.CmdRestart, 0)
|
||||
duties.MaxRestart = 4
|
||||
go duties.Duties()
|
||||
}
|
||||
|
||||
// IsPPP0Up Pppoe是否是UP的状态
|
||||
func (duties *DutiesNet) IsPPP0Up() bool {
|
||||
ifaces, err := net.Interfaces()
|
||||
if ErrorLog(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, i := range ifaces {
|
||||
if i.Name == "ppp0" {
|
||||
flags := strings.Split(i.Flags.String(), "|")
|
||||
if len(flags) > 0 {
|
||||
log.Println(flags)
|
||||
if flags[0] != "up" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsPPP1Exist ppp1是否是UP的状态
|
||||
func (duties *DutiesNet) IsPPP1Exist() bool {
|
||||
ifaces, err := net.Interfaces()
|
||||
if ErrorLog(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, i := range ifaces {
|
||||
if i.Name == "ppp1" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PPP0Restart ppp0 重启
|
||||
func (duties *DutiesNet) PPP0Restart() {
|
||||
log.Println("PPP0Restart")
|
||||
_, err := exec.Command("ifdown", "ppp1").Output()
|
||||
ErrorLog(err)
|
||||
_, err = exec.Command("ifdown", "ppp0").Output()
|
||||
ErrorLog(err)
|
||||
time.Sleep(time.Second * 1)
|
||||
_, err = exec.Command("ifdown", "ppp0").Output()
|
||||
ErrorLog(err)
|
||||
time.Sleep(time.Second * 1)
|
||||
_, err = exec.Command("ifup", "ppp0").Output()
|
||||
ErrorLog(err)
|
||||
time.Sleep(time.Second * 5)
|
||||
_, err = exec.Command("ip", "route", "replace", "default", "dev", "ppp0").CombinedOutput()
|
||||
ErrorLog(err)
|
||||
|
||||
atomic.StoreInt64(&duties.NetProtectTime, time.Now().Unix()+duties.MaxProtectTime)
|
||||
atomic.StoreInt64(&duties.CmdRestart, 0)
|
||||
}
|
||||
|
||||
// SetRestart 设置重启 异步
|
||||
func (duties *DutiesNet) SetRestart() {
|
||||
log.Println("SetRestart")
|
||||
now := time.Now().Unix()
|
||||
// 当前时间大于保护时间,才能进行重启的计算操作
|
||||
if now >= duties.NetProtectTime {
|
||||
log.Println("SetRestart Success")
|
||||
atomic.AddInt64(&duties.CmdRestart, duties.MaxRestart+20) // 设置超过最大的值的20, 保证重启.
|
||||
}
|
||||
}
|
||||
|
||||
func (duties *DutiesNet) checkError1() bool {
|
||||
if duties.IsPPP1Exist() {
|
||||
log.Println("IsPPP1Exist not")
|
||||
duties.PPP0Restart()
|
||||
return true
|
||||
}
|
||||
return false // 检测错误才返回true 否则 false
|
||||
}
|
||||
|
||||
func (duties *DutiesNet) checkError2() bool {
|
||||
// 检测3次ppp0是否处于Up的状态(pppoe有可能存在Down的状态, 这种错误. 但是判断为已经成功拨号)
|
||||
for i := 0; i < 4; i++ {
|
||||
if duties.IsPPP0Up() {
|
||||
return false
|
||||
}
|
||||
if i == 3 {
|
||||
log.Println("IsPPP0Up not")
|
||||
duties.PPP0Restart() // 强制重启, 不受最大值的限制
|
||||
return true
|
||||
}
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
//Duties 核心循环过程, 保证pppoe的网络可行
|
||||
func (duties *DutiesNet) Duties() {
|
||||
for {
|
||||
// 如果超过MaxRestart也会重启
|
||||
if atomic.LoadInt64(&duties.CmdRestart) > duties.MaxRestart {
|
||||
log.Println("CmdRestart ", atomic.LoadInt64(&duties.CmdRestart))
|
||||
duties.PPP0Restart()
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
// 如果网络不能ping通 执行下面的处理
|
||||
if !duties.PW.PingNet() {
|
||||
time.Sleep(time.Second * 1)
|
||||
atomic.AddInt64(&duties.CmdRestart, 1) // 重启因素的积累, 出一次错误就积累一次. 达到最大值后重启
|
||||
|
||||
if duties.checkError1() {
|
||||
continue
|
||||
}
|
||||
|
||||
if duties.checkError2() {
|
||||
continue
|
||||
}
|
||||
|
||||
} else {
|
||||
if atomic.LoadInt64(&duties.CmdRestart) > 0 {
|
||||
atomic.AddInt64(&duties.CmdRestart, -1) // 如果Ping成功就减少重启因素积累. 0为最低限制值
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
54
dutiesvpn.go
Normal file
54
dutiesvpn.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DutiesVPN VPN相关的责任
|
||||
type DutiesVPN struct {
|
||||
PW *PingWorker
|
||||
VPNProtectTime int64 // 保护时间
|
||||
MaxProtectTime int64 // 保护时间的最大值
|
||||
}
|
||||
|
||||
// Default 设置默认值
|
||||
func (duties *DutiesVPN) Default(pw *PingWorker) {
|
||||
duties.PW = pw
|
||||
atomic.StoreInt64(&duties.MaxProtectTime, 40) //保护时间初始化为40秒
|
||||
go duties.Duties()
|
||||
}
|
||||
|
||||
//Reset 重置
|
||||
func (duties *DutiesVPN) Reset() {
|
||||
atomic.StoreInt64(&duties.VPNProtectTime, time.Now().Unix())
|
||||
}
|
||||
|
||||
// RestartConnect 重置Openvpn连接
|
||||
func (duties *DutiesVPN) RestartConnect() {
|
||||
_, err := exec.Command("pkill", "openvpn").CombinedOutput()
|
||||
ErrorLog(err)
|
||||
atomic.StoreInt64(&duties.VPNProtectTime, time.Now().Unix()+duties.MaxProtectTime) //重启后给予40秒openvpn的重试时间
|
||||
}
|
||||
|
||||
// Duties 保证openvpn的可行
|
||||
func (duties *DutiesVPN) Duties() {
|
||||
|
||||
duties.Reset()
|
||||
|
||||
for {
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
if duties.PW.PingNet() {
|
||||
if !duties.PW.PingVPN() {
|
||||
now := time.Now().Unix()
|
||||
// openvpn需要一段时间connect 才能知道是否连接成功. 所以所有一段保护时间确保这段时间内是进行connect.
|
||||
if now >= atomic.LoadInt64(&duties.VPNProtectTime) {
|
||||
duties.RestartConnect()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
97
main.go
Normal file
97
main.go
Normal file
|
@ -0,0 +1,97 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrorPanic 错误检测
|
||||
func ErrorPanic(err error) {
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorLog 错误检测
|
||||
func ErrorLog(err error) bool {
|
||||
if err != nil {
|
||||
// log.Println(err)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Worker 维护所有系统正常的核心类
|
||||
type Worker struct {
|
||||
LogFile *os.File
|
||||
|
||||
DNET *DutiesNet
|
||||
DVPN *DutiesVPN
|
||||
}
|
||||
|
||||
func checkTunExist() bool {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, i := range ifaces {
|
||||
if i.Name == "tun0" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CmdRestartHandler 接收到该命令就重启
|
||||
func (worker *Worker) CmdRestartHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_tm := r.PostFormValue("tm")
|
||||
if _tm != "" {
|
||||
tm, err := strconv.ParseInt(_tm, 10, 64)
|
||||
if !ErrorLog(err) {
|
||||
log.Println(tm)
|
||||
worker.DNET.SetRestart()
|
||||
}
|
||||
}
|
||||
w.Write([]byte("ok"))
|
||||
}
|
||||
|
||||
// CmdImOKHandler 可以ping通
|
||||
func (worker *Worker) CmdImOKHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("ok"))
|
||||
}
|
||||
|
||||
func testSync(f *os.File) {
|
||||
for {
|
||||
time.Sleep(time.Second * 1)
|
||||
f.Sync()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(log.Lshortfile | log.LstdFlags)
|
||||
f, err := os.OpenFile("/root/pppoe_control.log", os.O_SYNC|os.O_APPEND|os.O_CREATE|os.O_RDWR, 0660)
|
||||
ErrorPanic(err)
|
||||
log.SetOutput(f)
|
||||
defer f.Close()
|
||||
go testSync(f)
|
||||
|
||||
pw := &PingWorker{}
|
||||
|
||||
dnet := &DutiesNet{}
|
||||
dnet.Default(pw)
|
||||
|
||||
dvpn := &DutiesVPN{}
|
||||
dvpn.Default(pw)
|
||||
|
||||
worker := Worker{f, dnet, dvpn}
|
||||
|
||||
http.HandleFunc("/pppoe/restart", worker.CmdRestartHandler)
|
||||
http.HandleFunc("/pppoe/imok", worker.CmdImOKHandler)
|
||||
http.ListenAndServe(":8800", nil)
|
||||
}
|
64
pingworker.go
Normal file
64
pingworker.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PingWorker 专为ping服务, 保证不存在多余的Ping的, 让终端服务的请求合理减少.
|
||||
type PingWorker struct {
|
||||
LastPingVPNTime int64
|
||||
LastPingVPN int64 //上次Ping的结果 0 或者 1
|
||||
|
||||
LastPingNetTime int64
|
||||
LastPingNet int64 //上次Ping的结果 0 或者 1
|
||||
}
|
||||
|
||||
// PingNet 确认adsl网络通信
|
||||
func (pw *PingWorker) PingNet() bool {
|
||||
now := time.Now().Unix()
|
||||
if now-atomic.LoadInt64(&pw.LastPingNetTime) <= 2 {
|
||||
return atomic.LoadInt64(&pw.LastPingNet) == 1
|
||||
}
|
||||
|
||||
timeout := time.Duration(5 * time.Second)
|
||||
client := http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
_, err := client.Get("http://14.17.96.148:3333/ippool/switch/imactive")
|
||||
if err != nil {
|
||||
log.Println("PingNet err http://14.17.96.148:3333/ippool/switch/imactive check Network")
|
||||
atomic.StoreInt64(&pw.LastPingNet, 0)
|
||||
atomic.StoreInt64(&pw.LastPingNetTime, time.Now().Unix())
|
||||
return false
|
||||
}
|
||||
atomic.StoreInt64(&pw.LastPingNet, 1)
|
||||
atomic.StoreInt64(&pw.LastPingNetTime, time.Now().Unix())
|
||||
return true
|
||||
}
|
||||
|
||||
// PingVPN 确认确认外网网络通信
|
||||
func (pw *PingWorker) PingVPN() bool {
|
||||
now := time.Now().Unix()
|
||||
if now-atomic.LoadInt64(&pw.LastPingVPNTime) <= 2 {
|
||||
return atomic.LoadInt64(&pw.LastPingVPN) == 1
|
||||
}
|
||||
|
||||
timeout := time.Duration(5 * time.Second)
|
||||
client := http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
_, err := client.Get("http://10.10.10.1:3333/ippool/switch/imactive")
|
||||
if err != nil {
|
||||
log.Println("PingVPN err http://10.10.10.1:3333/ippool/switch/imactive check Network")
|
||||
atomic.StoreInt64(&pw.LastPingVPN, 0)
|
||||
atomic.StoreInt64(&pw.LastPingVPNTime, time.Now().Unix())
|
||||
return false
|
||||
}
|
||||
|
||||
atomic.StoreInt64(&pw.LastPingVPN, 1)
|
||||
atomic.StoreInt64(&pw.LastPingVPNTime, time.Now().Unix())
|
||||
return true
|
||||
}
|
13
pppoe_control.service
Normal file
13
pppoe_control.service
Normal file
|
@ -0,0 +1,13 @@
|
|||
[Unit]
|
||||
Description=pppoe_control
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
PIDFile=/var/run/pppoe_control.pid
|
||||
ExecStart=/usr/local/bin/pppoe_control
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Loading…
Reference in New Issue
Block a user