1
0
mirror of https://github.com/taigrr/godns synced 2025-01-18 04:03:25 -08:00

Merge pull request #2 from abotoo/master

daemonize it using code instead of using nohup command
This commit is contained in:
Timothy Ye 2015-02-25 21:20:00 +08:00
commit b9780b7566
6 changed files with 121 additions and 98 deletions

View File

@ -2,9 +2,9 @@
[![Build Status](https://travis-ci.org/TimothyYe/godns.svg?branch=master)](https://travis-ci.org/TimothyYe/godns)
GoDNS is a dynamic DNS (DDNS) tool, it is based on my early open source project: [DynDNS](https://github.com/TimothyYe/DynDNS).
GoDNS is a dynamic DNS (DDNS) tool, it is fork from: [GoDNS](https://github.com/TimothyYe/godns).
Now I rewrite [DynDNS](https://github.com/TimothyYe/DynDNS) by Golang and call it [GoDNS](https://github.com/TimothyYe/godns).
Modify something.
## Pre-condition
@ -19,7 +19,7 @@ Now I rewrite [DynDNS](https://github.com/TimothyYe/DynDNS) by Golang and call i
* Get source code from Github:
```bash
git clone https://github.com/TimothyYe/godns.git
git clone https://github.com/abotoo/godns.git
```
* Go into the godns directory, get related library and then build it:
@ -30,21 +30,17 @@ go build
```
* Then you get GoDNS.
### Build godns from the 3rd party
* Visit this URL provided by [GoBuild](http://gobuild.io/download/github.com/TimothyYe/godns).
* Select the platform you need.
* Input the build type and branch name.
* Build and download GoDNS.
## Run it
* Get [config_sample.json](https://github.com/TimothyYe/godns/blob/master/config_sample.json) from Github.
* Get [config_sample.json](https://github.com/abotoo/godns/blob/master/config_sample.json) from Github.
* Rename it to **config.json**.
* Configure your domain/sub-domain info, username and password of DNSPod account.
* Save it in the same directory of GoDNS.
* Configure log file path, max size of log file, max count of log file.
* Configure user id, group id for safty.
* Save it in the same directory of GoDNS, or use -c=your_conf_path command.
* The last step, run godns:
```bash
nohup ./godns &
./godns
```
* Enjoy it!

View File

@ -3,5 +3,10 @@
"password": "",
"domain": "",
"sub_domain": "",
"ip_url": "http://members.3322.org/dyndns/getip"
"ip_url": "http://members.3322.org/dyndns/getip",
"log_path":"./godns.log",
"log_size":16,
"log_num":3,
"user":0,
"group":0
}

View File

@ -3,21 +3,21 @@ package main
import (
"encoding/json"
"fmt"
"github.com/bitly/go-simplejson"
log "github.com/cihub/seelog"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/bitly/go-simplejson"
)
func get_currentIP(url string) (string, error) {
response, err := http.Get(url)
if err != nil {
fmt.Println("Cannot get IP...")
log.Error("Cannot get IP...")
log.Println("Cannot get IP...")
return "", err
}
@ -60,16 +60,14 @@ func get_domain(name string) int64 {
response, err := post_data("/Domain.List", values)
if err != nil {
fmt.Println("Failed to get domain list...")
log.Error("Failed to get domain list...")
log.Println("Failed to get domain list...")
return -1
}
sjson, parse_err := simplejson.NewJson([]byte(response))
if parse_err != nil {
fmt.Println(parse_err.Error())
log.Error(parse_err.Error())
log.Println(parse_err)
return -1
}
@ -89,12 +87,18 @@ func get_domain(name string) int64 {
break
}
}
if len(domains) == 0 {
log.Println("domains slice is empty.")
}
} else {
log.Println("get_domain:status code:", sjson.Get("status").Get("code").MustString())
}
return ret
}
func get_subdomain(domain_id int64, name string) (string, string) {
log.Println("debug:", domain_id, name)
var ret, ip string
value := url.Values{}
value.Add("domain_id", strconv.FormatInt(domain_id, 10))
@ -105,16 +109,14 @@ func get_subdomain(domain_id int64, name string) (string, string) {
response, err := post_data("/Record.List", value)
if err != nil {
fmt.Println("Failed to get domain list...")
log.Error("Failed to get domain list")
log.Println("Failed to get domain list")
return "", ""
}
sjson, parse_err := simplejson.NewJson([]byte(response))
if parse_err != nil {
fmt.Println(parse_err.Error())
log.Error(parse_err.Error())
log.Println(parse_err)
return "", ""
}
@ -129,6 +131,11 @@ func get_subdomain(domain_id int64, name string) (string, string) {
break
}
}
if len(records) == 0 {
log.Println("records slice is empty.")
}
} else {
log.Println("get_subdomain:status code:", sjson.Get("status").Get("code").MustString())
}
return ret, ip
@ -146,25 +153,20 @@ func update_ip(domain_id int64, sub_domain_id string, sub_domain_name string, ip
response, err := post_data("/Record.Modify", value)
if err != nil {
fmt.Println("Failed to update record to new IP!")
fmt.Println(err.Error())
log.Error("Failed to update record to new IP!")
log.Error(err.Error())
log.Println("Failed to update record to new IP!")
log.Println(err)
return
}
sjson, parse_err := simplejson.NewJson([]byte(response))
if parse_err != nil {
fmt.Println(parse_err.Error())
log.Error(parse_err.Error())
log.Println(parse_err)
return
}
if sjson.Get("status").Get("code").MustString() == "1" {
fmt.Println("New IP updated!")
log.Info("New IP updated!")
log.Println("New IP updated!")
}
}
@ -181,11 +183,8 @@ func post_data(url string, content url.Values) (string, error) {
defer response.Body.Close()
if err != nil {
fmt.Println("Post failed...")
fmt.Println(err.Error())
log.Error("Post failed...")
log.Error(err.Error())
log.Println("Post failed...")
log.Println(err)
return "", err
}

108
godns.go
View File

@ -1,51 +1,87 @@
package main
import (
"fmt"
log "github.com/cihub/seelog"
"os"
"flag"
"log"
"runtime/debug"
"strings"
"syscall"
"time"
"bitbucket.org/abotoo/gonohup"
)
var Configuration Settings
const (
PANIC_MAX = 5
INTERVAL = 5 //Minute
)
var (
Configuration Settings
optConf = flag.String("c", "./config.json", "config file")
optCommand = flag.String("s", "", "send signal to a master process: stop, quit, reopen, reload")
optHelp = flag.Bool("h", false, "this help")
panicCount = 0
)
func usage() {
log.Println("[command] -c=[config file path]")
flag.PrintDefaults()
}
func main() {
initLog()
flag.Parse()
if *optHelp {
usage()
return
}
fmt.Println("Starting...")
log.Info("Starting...")
Configuration = LoadSettings(*optConf)
Configuration = LoadSettings()
ctx := gonohup.Context{
Hash: "godns",
User: Configuration.User,
Group: Configuration.Group,
Command: *optCommand,
}
sig, err := gonohup.Daemonize(ctx)
if err != nil {
log.Println("Daemonize:", err)
return
}
loop := make(chan bool)
go dns_loop(loop)
err = gonohup.InitLogger(Configuration.Log_Path, Configuration.Log_Size, Configuration.Log_Num)
if err != nil {
log.Println("InitLogger error:", err)
return
}
ret := <-loop
go dns_loop()
if !ret {
fmt.Println("Dns loop exited...")
log.Error("Dns loop exited...")
close(loop)
os.Exit(1)
for s := range sig {
switch s {
case syscall.SIGHUP, syscall.SIGUSR2:
// do some custom jobs while reload/hotupdate
case syscall.SIGTERM:
// do some clean up and exit
return
}
}
}
func dns_loop(loop chan bool) {
func dns_loop() {
defer func() {
if err := recover(); err != nil {
panicCount++
log.Printf("Recovered in %v: %v\n", err, debug.Stack())
if panicCount < PANIC_MAX {
log.Println("Got panic in goroutine, will start a new one... :", panicCount)
go dns_loop()
}
}
}()
for {
defer func() {
if err := recover(); err != nil {
log.Error(err)
log.Info("Stack trace:\n" + string(debug.Stack()))
log.Info("Got panic in goroutine, will start a new one...")
go dns_loop(loop)
}
}()
domain_id := get_domain(Configuration.Domain)
if domain_id == -1 {
@ -55,34 +91,30 @@ func dns_loop(loop chan bool) {
currentIP, err := get_currentIP(Configuration.IP_Url)
if err != nil {
log.Println("get_currentIP:", err)
continue
}
sub_domain_id, ip := get_subdomain(domain_id, Configuration.Sub_domain)
if sub_domain_id == "" || ip == "" {
log.Println("sub_domain:", sub_domain_id, ip)
continue
}
fmt.Printf("currentIp is:%s\n", currentIP)
log.Infof("currentIp is:%s\n", currentIP)
log.Println("currentIp is:", currentIP)
//Continue to check the IP of sub-domain
if len(ip) > 0 && !strings.Contains(currentIP, ip) {
fmt.Println("Start to update record IP...")
log.Info("Start to update record IP...")
log.Println("Start to update record IP...")
update_ip(domain_id, sub_domain_id, Configuration.Sub_domain, currentIP)
} else {
fmt.Println("Current IP is same as domain IP, no need to update...")
log.Info("Current IP is same as domain IP, no need to update...")
log.Println("Current IP is same as domain IP, no need to update...")
}
//Interval is 5 minutes
time.Sleep(time.Second * 60 * 5)
time.Sleep(time.Minute * INTERVAL)
}
log.Info("Loop exited...")
loop <- false
log.Printf("Loop %d exited...\n", panicCount)
}

View File

@ -1,15 +0,0 @@
package main
import log "github.com/cihub/seelog"
func initLog() {
testConfig := `
<seelog>
<outputs>
<rollingfile type="size" filename="./run.log" maxsize="10000" maxrolls="5" />
</outputs>
</seelog>
`
logger, _ := log.LoggerFromConfigAsBytes([]byte(testConfig))
log.ReplaceLogger(logger)
}

View File

@ -7,26 +7,32 @@ import (
"os"
)
const config_path string = "config.json"
type Settings struct {
Email string
Password string
Domain string
Sub_domain string
IP_Url string
Log_Path string
Log_Size int
Log_Num int
User int
Group int
}
func LoadSettings() Settings {
func LoadSettings(config_path string) Settings {
file, err := ioutil.ReadFile(config_path)
if err != nil {
fmt.Println("Error occurs while reading config file, please make sure config file exists!")
os.Exit(1)
}
var setting Settings
json.Unmarshal(file, &setting)
err = json.Unmarshal(file, &setting)
if err != nil {
fmt.Println("Error occurs while unmarshal config file, please make sure config file correct!")
os.Exit(1)
}
return setting
}