Last active
October 25, 2018 20:26
-
-
Save lixin9311/c9508f15098b56959fd60dc4d78444cc to your computer and use it in GitHub Desktop.
watchdog
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"io" | |
"log" | |
"net" | |
"os" | |
"time" | |
"unsafe" | |
"golang.org/x/sys/unix" | |
) | |
const ( | |
dog = "/dev/watchdog" | |
) | |
func getTimeout(fd *os.File) (int, error) { | |
ufd := int(fd.Fd()) | |
return unix.IoctlGetInt(ufd, unix.WDIOC_GETTIMEOUT) | |
} | |
func setTimeout(fd *os.File, timeout int) (err error) { | |
ufd := int(fd.Fd()) | |
return unix.IoctlSetInt(ufd, unix.WDIOC_SETTIMEOUT, int(uintptr(unsafe.Pointer(&timeout)))) | |
} | |
func checkLastBoot(fd *os.File) (bool, error) { | |
ufd := int(fd.Fd()) | |
if result, err := unix.IoctlGetInt(ufd, unix.WDIOC_GETBOOTSTATUS); err != nil { | |
return false, err | |
} else { | |
return result != 0, nil | |
} | |
} | |
func ping(fd *os.File) (err error) { | |
ufd := int(fd.Fd()) | |
return unix.IoctlSetInt(ufd, unix.WDIOC_KEEPALIVE, 0) | |
} | |
func close(fd *os.File) error { | |
return unix.Close(int(fd.Fd())) | |
} | |
func testHost(host string) error { | |
if conn, err := net.DialTimeout("tcp", host, time.Second); err != nil { | |
return err | |
} else { | |
conn.Close() | |
} | |
return nil | |
} | |
func main() { | |
isClean := flag.Bool("clean", false, "Close the watchdog device. Some systems with nowayout flag does not support close.") | |
// isCheck := flag.Check("check", false, "Check wether the last boot was caused by watchdog") | |
interval := flag.Int("i", 60, "Timeout interval. Some hardware does not support change the timeout.") | |
ratio := flag.Float64("r", 0.5, "Ping interval ratio to the timeout.") | |
host := flag.String("h", "localhost:22", "The target host you want to ping.") | |
logFile := flag.String("l", "/tmp/watchdog.log", "log file.") | |
flag.Parse() | |
if logf, err := os.OpenFile(*logFile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644); err != nil { | |
log.Printf("Failed to open log file, %v", err) | |
} else { | |
defer logf.Close() | |
logWriter := io.MultiWriter(os.Stderr, logf) | |
log.SetOutput(logWriter) | |
} | |
if _, err := os.Stat(dog); os.IsNotExist(err) { | |
log.Printf("HW Watchdog may not exist, please load softdog.\n") | |
return | |
} | |
fdog, err := os.OpenFile(dog, os.O_WRONLY, 0644) | |
if err != nil { | |
log.Printf("Failed to open watchdog, %v\n", err) | |
return | |
} | |
defer fdog.Close() | |
defer log.Println("Watchdog closed.") | |
if *isClean { | |
return | |
} | |
last, err := checkLastBoot(fdog) | |
if err != nil { | |
log.Printf("Failed to check the cause of last boot\n") | |
} else { | |
if last { | |
log.Printf("Last boot was casue by WATCHDOG\n") | |
} else { | |
log.Printf("Last boot was casue by RESET\n") | |
} | |
} | |
timeout, err := getTimeout(fdog) | |
if err != nil { | |
log.Printf("Failed to get current timeout of watchdog, %v\n", err) | |
return | |
} | |
log.Printf("Current timeout is [%ds].\n", timeout) | |
err = setTimeout(fdog, *interval) | |
if err != nil { | |
log.Printf("Failed to set timeout, %v\n", err) | |
log.Printf("Use default timeout [%ds].", timeout) | |
} else { | |
timeout, err = getTimeout(fdog) | |
if err != nil { | |
log.Printf("Failed to get current timeout of watchdog, %v\n", err) | |
return | |
} | |
log.Printf("Timeout is set to [%ds].\n", timeout) | |
} | |
duration := int(float64(timeout) * *ratio) | |
if duration < 1 { | |
duration = 1 | |
} | |
log.Printf("Will ping the watchdog with interval [%ds].", duration) | |
for { | |
if err := testHost(*host); err != nil { | |
log.Printf("Cannot establish connetion to %s, %v", *host, err) | |
} else { | |
ping(fdog) | |
} | |
time.Sleep(time.Duration(duration) * time.Second) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment