hg5145f 续
之前尝试通过修改分区的方式来实现光猫开机自启程序,但是因为分区无法写入最终告一段落,现在换一个思路。
通过一台设备监测光猫接口变动,自动开启telent并执行特定脚本拉起其他脚本
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"regexp"
"strings"
"time"
"github.com/google/goexpect"
"github.com/vishvananda/netlink"
)
// Config struct to hold the configuration
type Config struct {
Address string `json:"address"`
User string `json:"user"`
Pass string `json:"pass"`
Cmd string `json:"cmd"`
TelnetPort string `json:"telnet_port"`
TelnetURL string `json:"telnet_url"`
UserRE string `json:"user_re"`
PassRE string `json:"pass_re"`
PromptRE string `json:"prompt_re"`
}
// Default configuration values
var defaultConfig = Config{
Address: "192.168.1.1",
User: "admin",
Pass: "password123",
Cmd: "show version",
TelnetPort: "23",
TelnetURL: "http://192.168.1.1/cgi-bin/telnetenable.cgi?telnetenable=1&key=D078800E0CD0",
UserRE: "login:",
PassRE: "Password:",
PromptRE: "admin@*",
}
// Function to load configuration from a JSON file
func loadConfig(filename string) (*Config, error) {
// File doesn't exist, create it and write default values
if _, err := os.Stat(filename); os.IsNotExist(err) {
log.Println("Config file not found, creating a new one with default values.")
file, err := os.Create(filename)
if err != nil {
return nil, fmt.Errorf("failed to create config file: %v", err)
}
defer file.Close()
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ")
encoder.SetEscapeHTML(false)
if err := encoder.Encode(defaultConfig); err != nil {
return nil, fmt.Errorf("failed to write default config to file: %v", err)
}
log.Printf("Default config written to %s", filename)
os.Exit(0)
}
// If the file exists, read and parse it
file, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("failed to open config file: %v", err)
}
defer file.Close()
var config Config
if err := json.NewDecoder(file).Decode(&config); err != nil {
return nil, fmt.Errorf("parse config file: %v", err)
}
return &config, nil
}
func enableTelnet(url string) error {
ip := strings.Split(strings.Split(url, "://")[1], "/")[0]
if strings.Contains(ip, ":") {
ip = strings.Split(ip, ":")[0]
}
for {
if _, err := net.DialTimeout("tcp", ip+":80", 2*time.Second); err == nil {
break
}
log.Printf("Unable to connect to %s, retrying...", ip)
time.Sleep(10 * time.Second)
}
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("telnet enable request failed: %v", err)
}
defer resp.Body.Close()
buf, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("read response failed: %v", err)
}
if !strings.Contains(string(buf), "telnet开启") {
return fmt.Errorf("telnet enable failed")
}
log.Println("Telnet enabled successfully")
return nil
}
func runExpect(config *Config) error {
const timeout = 60 * time.Second
// Compile regular expressions
userRE, err := regexp.Compile(config.UserRE)
if err != nil {
return fmt.Errorf("compile user RE: %v", err)
}
passRE, err := regexp.Compile(config.PassRE)
if err != nil {
return fmt.Errorf("compile pass RE: %v", err)
}
promptRE, err := regexp.Compile(config.PromptRE)
if err != nil {
return fmt.Errorf("compile prompt RE: %v", err)
}
for {
e, _, err := expect.Spawn(fmt.Sprintf("telnet %s %s", config.Address, config.TelnetPort), -1)
if err != nil {
log.Fatal(err)
}
defer e.Close()
e.Expect(userRE, timeout)
e.Send(config.User + "\n")
e.Expect(passRE, timeout)
e.Send(config.Pass + "\n")
e.Expect(promptRE, timeout)
e.Send(config.Cmd + "\n")
result, _, _ := e.Expect(promptRE, timeout)
e.Send("exit\n")
fmt.Println(result)
log.Println("Command run successfully")
return nil
}
}
func monitorNetwork(config *Config, iface string) {
linkUpdates := make(chan netlink.LinkUpdate)
done := make(chan struct{})
if err := netlink.LinkSubscribe(linkUpdates, done); err != nil {
log.Fatalf("Failed to subscribe to netlink updates: %v", err)
}
for update := range linkUpdates {
if update.Attrs().Name != iface || update.Attrs().Flags&net.FlagUp == 0 {
continue
}
log.Println("Network change detected, running commands...")
if err := enableTelnet(config.TelnetURL); err != nil {
log.Printf("Telnet error: %v", err)
} else if err := runExpect(config); err != nil {
log.Printf("Expect error: %v", err)
}
}
}
func main() {
iface := flag.String("iface", "", "Network interface to monitor")
daemon := flag.Bool("d", false, "Run in daemon mode")
configFile := flag.String("c", "config.json", "Configuration file path")
flag.Parse()
config, err := loadConfig(*configFile)
if err != nil {
log.Fatal(err)
}
if err := enableTelnet(config.TelnetURL); err != nil {
log.Fatal(err)
}
if err := runExpect(config); err != nil {
log.Fatal(err)
}
if *daemon {
if *iface == "" {
log.Fatal("Network interface must be specified in daemon mode using -iface flag")
}
log.Printf("Running in daemon mode, monitoring interface: %s", *iface)
go monitorNetwork(config, *iface)
select {}
}
}代码基本由ai编写,个人仅提供思路和修改报错
GOARCH=arm64 GOOS=linux go build -ldflags "-s -w" -trimpath{
"address": "192.168.123.1",
"user": "admin",
"pass": "Fh@0E0CD0",
"cmd": "/osgi/custom/main.sh",
"telnet_port": "23",
"telnet_url": "http://192.168.123.1/cgi-bin/telnetenable.cgi?telnetenable=1&key=D078800E0CD0",
"user_re": "login:",
"pass_re": "Password:",
"prompt_re": "admin@*"
}
暂无标签