diff --git a/Makefile b/Makefile index abdc58c..a8b9883 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +SHELL := /bin/bash + VERSION=$(shell git describe --tags) BUILD=$(shell git rev-parse --short HEAD) PROJ := $(shell basename "$(PWD)") @@ -25,13 +27,13 @@ build-unix: $(shell export GOOS=$(GOOS); export GOARCH=$(GOARCH); go build ${LDFLAGS} -o dist/$(PROJ)_$(VERSION)_$(GOOS)_$(GOARCH)/$(PROJ)))) build-win: - $(shell export GOOS=windows; export GOARCH=arm64; go build ${LDFLAGS} -o dist/$(PROJ)_$(VERSION)_windows_arm64/$(PROJ).exe) + $(shell export GOOS=windows; export GOARCH=amd64; go build ${LDFLAGS} -o dist/$(PROJ)_$(VERSION)_windows_amd64/$(PROJ).exe) build-mac-m1: $(shell export GOOS=darwin; export GOARCH=arm64; go build ${LDFLAGS} -o dist/$(PROJ)_$(VERSION)_darwin_arm64/$(PROJ)) build-zip: - cd dist; for f in * ;do tar -czf $${f}.tar.gz $${f}; done + cd dist; for f in * ;do if ! [[ $$f =~ "gz" ]] ; then tar -czf $${f}.tar.gz $${f}; fi done binary: build-unix build-win build-mac-m1 diff --git a/README.md b/README.md index 1a02c48..1714486 100644 --- a/README.md +++ b/README.md @@ -19,16 +19,20 @@ Available Commands: Flags: -a, --all show local ip -c, --cell show cell, must used with --list + --cron run as cron service -h, --help help for myip -u, --host string hostname to connect (default "kumoly.io") -l, --list show list + -n, --name string tell the server who you are --no-pub disable PublicIP -p, --port string server port to connect (default "5080") --secure use https + -s, --spec string hostname to connect (default "0 */5 * * * *") -t, --title show title, used with --list -v, --version version for myip Use "myip [command] --help" for more information about a command. + ``` ## Docker @@ -40,6 +44,12 @@ docker pull hub.kumoly.io/tools/myip:latest docker run --name myip-server -d -p 5080:5080 --restart=always hub.kumoly.io/tools/myip ``` +Client: + +```shell +docker pull hub.kumoly.io/tools/myip:latest +docker run --name myip -d --restart=always hub.kumoly.io/tools/myip myip --cron --spec "@hourly" +``` ## Cron @@ -52,6 +62,16 @@ Hours | Yes | 0-23 | * / , - Day of month | Yes | 1-31 | * / , - ? Month | Yes | 1-12 or JAN-DEC | * / , - Day of week | Yes | 0-6 or SUN-SAT | * / , - ? + +Entry | Description | Equivalent To +----- | ----------- | ------------- +@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 * +@monthly | Run once a month, midnight, first of month | 0 0 0 1 * * +@weekly | Run once a week, midnight between Sat/Sun | 0 0 0 * * 0 +@daily (or @midnight) | Run once a day, midnight | 0 0 0 * * * +@hourly | Run once an hour, beginning of hour | 0 0 * * * * + +@every ``` **Duration**: `myip -altc --cron --spec "@every 5m"` diff --git a/cmd/client.go b/cmd/client.go index b467518..83fd83f 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -8,8 +8,10 @@ import ( "net" "net/http" "os" + "sort" "strings" "text/tabwriter" + "time" "github.com/robfig/cron/v3" "github.com/spf13/cobra" @@ -32,6 +34,12 @@ var ( cronSpec string ) +type Iface struct { + IP string + HardwareAddr string + Name string +} + var ClientCmd = &cobra.Command{ Use: "myip", Short: "myip is a easy way to get public ip of current system.", @@ -110,8 +118,8 @@ func Scan() error { if !noPub { fmt.Fprintf(w, "\t%v\t%v\t\n", "PublicIP", ip) } - for k, v := range local { - fmt.Fprintf(w, "\t%v\t%v\t\n", k, v) + for _, iface := range local { + fmt.Fprintf(w, "\t%v\t%v\t\n", iface.Name, iface.IP) } return w.Flush() @@ -120,7 +128,7 @@ func Scan() error { fmt.Printf("%v ", ip) } for _, v := range local { - fmt.Printf("%v ", v) + fmt.Printf("%v ", v.IP) } fmt.Printf("\n") } @@ -128,8 +136,8 @@ func Scan() error { return nil } -func GetLocalIP() (map[string]string, error) { - ret := map[string]string{} +func GetLocalIP() ([]Iface, error) { + ret := []Iface{} ifaces, err := net.Interfaces() if err != nil { log.Println(err) @@ -161,10 +169,17 @@ func GetLocalIP() (map[string]string, error) { // continue // } } - ret[i.Name] = ip.String() + ret = append(ret, Iface{ + IP: ip.String(), + Name: i.Name, + HardwareAddr: i.HardwareAddr.String(), + }) break } } + sort.Slice(ret, func(i, j int) bool { + return ret[i].Name < ret[j].Name + }) return ret, nil } @@ -173,7 +188,11 @@ func GetPublicIP() (string, error) { if secure { protocol = "https://" } - res, err := http.Get(protocol + host + ":" + port + "?name=" + name) + req, _ := http.NewRequest("GET", protocol+host+":"+port+"?name="+name, nil) + client := &http.Client{ + Timeout: time.Second * 10, + } + res, err := client.Do(req) if err != nil { log.Println(err) return "", err diff --git a/cmd/server.go b/cmd/server.go index 3d1bdc9..62e81a5 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -5,6 +5,7 @@ import ( "log" "net" "net/http" + "time" "github.com/spf13/cobra" ) @@ -31,19 +32,16 @@ func init() { func StartServer() error { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - ip := r.Header.Get("X-Real-Ip") - if ip == "" { - ip = r.Header.Get("X-Forwarded-For") - } - if ip == "" { - var err error - ip, _, err = net.SplitHostPort(r.RemoteAddr) - if err != nil { - ip = r.RemoteAddr - } - } - r.Header.Add("X-Myip", ip) + ip := GetIP(r) fmt.Fprint(w, ip+"\n") + + // logging + user := r.URL.Query().Get("name") + if user == "" { + user = r.URL.String() + } + host, _, _ := net.SplitHostPort(r.RemoteAddr) + log.Printf("%s %s %s %s %s\n", time.Now().Format("2006-01-02-15:04:05"), host, ip, user, r.Header.Get("User-Agent")) }) err := http.ListenAndServe(addr+":"+port, simpleLogger(http.DefaultServeMux)) @@ -54,6 +52,21 @@ func StartServer() error { return nil } +func GetIP(r *http.Request) string { + ip := r.Header.Get("X-Real-Ip") + if ip == "" { + ip = r.Header.Get("X-Forwarded-For") + } + if ip == "" { + var err error + ip, _, err = net.SplitHostPort(r.RemoteAddr) + if err != nil { + ip = r.RemoteAddr + } + } + return ip +} + func simpleLogger(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -63,11 +76,7 @@ func simpleLogger(handler http.Handler) http.Handler { // fmt.Println(name, value) // } // } - user := r.URL.Query().Get("name") - if user == "" { - user = r.URL.String() - } - log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, user, r.Header.Get("User-Agent")) + // log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, r.URL, r.Header.Get("User-Agent")) handler.ServeHTTP(w, r) }) }