package sys import ( "basic.com/valib/bhomedbapi.git" "basic.com/valib/logger.git" "errors" "github.com/satori/go.uuid" "os" "os/exec" "regexp" "strconv" "vamicro/config" "vamicro/extend/util" "vamicro/system-service/iwlist" "vamicro/system-service/models" sysVo "vamicro/system-service/vo" "fmt" "net" "strings" "time" ) func execRootCommand(cmd string) ([]byte, error) { pwd := config.Server.SudoPassword cmdStr := fmt.Sprintf("echo %s | sudo -S %s", pwd, cmd) logger.Debug("root run:" + cmd) return exec.Command("/bin/bash", "-c", cmdStr).Output() } // 检查 root权限 func CheckRootPermissions() bool { showRootCMD := exec.Command("/bin/bash", "-c", "ls /root/") if _, err := showRootCMD.Output(); err != nil { return false } return true } // 获取本机网卡IP func GetLocalIP(networkName string) (ipv4 string, mask string, err error) { interfaces, err := net.Interfaces() if err != nil { return "", "", err } for _, i := range interfaces { byName, err := net.InterfaceByName(i.Name) if err != nil { return "", "", err } addresses, err := byName.Addrs() for _, v := range addresses { if ipnet, ok := v.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { if byName.Name == networkName { maskStr := ipnet.Mask.String() mask64, _ := strconv.ParseUint(maskStr, 16, 32) return ipnet.IP.String(), util.IpIntToString(int(mask64)), nil } } } } } return "", "", errors.New("IPv4尚未设置") } // 获取本机网关ip func GetDefaultRoute(networkName string) (route string, err error) { cmdStr := fmt.Sprintf("ip route show | grep -P \"^default.*%s\" | awk '{printf $3}'", networkName) cmd := exec.Command("/bin/sh", "-c", cmdStr) b, err := cmd.Output() if err != nil { return "", err } return string(b), nil } func GetDnsServer() (dns string, err error) { cmd := exec.Command("/bin/sh", "-c", "cat /etc/resolv.conf | grep nameserver | grep -v '#' | head -1 |awk '{printf $2}'") b, err := cmd.Output() if err != nil { return "", err } return string(b), nil } // 配置服务器网络 func SetNetworkConfig(ipv4, netmask, gateway, dns string, ifname string) (bool, string) { networkConfigScript := "/opt/vasystem/script/netconfig" //ifname := config.Server.NetworkAdapter localIPv4, localNetMask, err := GetLocalIP(ifname) if err != nil { //return false, err.Error() } localGW, err := GetDefaultRoute(ifname) if err != nil { return false, err.Error() } localDNS, _ := GetDnsServer() if localIPv4 == ipv4 && localNetMask == netmask && localGW == gateway && localDNS == dns { return true, "" } // 检查文件是否存在 if _, err := os.Stat(networkConfigScript); err != nil { return false, "network Config Script not exist" } // # netconfig enp59s0f0 192.168.1.2 255.255.255.0 192.168.1.1 192.168.100.1 cmdStr := fmt.Sprintf("%s %s %s %s %s %s", networkConfigScript, ifname, ipv4, netmask, gateway, dns) stdout, err := execRootCommand(cmdStr) if nil == err { return true, string(stdout) } return false, err.Error() + ":" + string(stdout) + "some wrong happens" } // GetNetWorkInfo 获取网卡配置信息 func GetNetWorkInfo(ifname string) (map[string]string, error) { var localIPv4, localNetMask, localGW, localDNS string var err error // 网卡未配置ip的情况下, 其他信息也需要显示为空. localIPv4, localNetMask, err = GetLocalIP(ifname) if err == nil { localGW, err = GetDefaultRoute(ifname) localDNS, err = GetDnsServer() } info := make(map[string]string, 0) info["ifname"] = ifname info["ip"] = localIPv4 info["subMask"] = localNetMask info["gateway"] = localGW info["dns"] = localDNS return info, err } // 获取网卡信息 func GetNetWorkCards() ([]sysVo.NetWorkCard, error) { interfaces, err := net.Interfaces() if nil != err { return nil, err } //获取无线网卡 iwDevMap := make(map[string]string, 0) iwDevs, err := GetIwDev() if nil == err { for _, item := range iwDevs { iwDevMap[item] = item } } //获取网卡LOWER_UP状态 lowerUpState := "" content, err := execRootCommand("ip addr show|grep LOWER_UP") if nil == err { lowerUpState = string(content) } l := len(interfaces) var data = make([]sysVo.NetWorkCard, 0, l) for _, interface1 := range interfaces { if strings.Contains(interface1.Flags.String(), "loopback") { continue } _, ok := iwDevMap[interface1.Name] lowerUp := strings.Contains(lowerUpState, interface1.Name) Addrs, _ := interface1.Addrs() data = append(data, sysVo.NetWorkCard{ Name: interface1.Name, Index: interface1.Index, MTU: interface1.MTU, Flags: interface1.Flags.String(), WireLess: ok, LowerUp: lowerUp, Addrs: Addrs, }) } return data, nil } // 修改IP发布消息 func IpChangePublish(newIp string) bool { //修改国标ip tmpResourceConf := models.ResourceConfig{} rcErr := tmpResourceConf.Select() var gbApi bhomedbapi.Gb28181Api flag, gbConf := gbApi.Show() if flag { //国标已配置 setGbIp := "" if rcErr == nil { //对外服务已配置 if tmpResourceConf.IpType == models.IpType_Local { //配置的是本机Ip setGbIp = newIp } else { //设置的是对外服务,则不需要刷新了 } } else { //对外服务ip未配置,国标使用本机ip setGbIp = newIp } if setGbIp != "" && setGbIp != gbConf.ServerIp { gbConf.ServerIp = setGbIp paramBody := util.Struct2Map(gbConf) return gbApi.Edit(paramBody) } } return false } /* * 更新配置 @param serverName 服务名称 @param newIp 服务Ip @return bool 是否是新创建的配置 @return error 错误信息 */ func ConfigUpdate(serverName, newIp string) (bool, error) { if "" == serverName && "" == newIp { return false, errors.New("参数错误") } conf := new(models.LocalConfig) logger.Debug("saveServerInfo serverName:", serverName) if err := conf.Select(); err != nil { // 查询是否存在 logger.Debug("saveServerInfo err:", err) return false, err } else { // 存在及修改 不存在 即添加 if "" != serverName { conf.ServerName = serverName } conf.ServerId = config.Server.AnalyServerId logger.Debug("saveServerInfo newIp:", newIp) if newIp != "" && (conf.AlarmIp != newIp || conf.WebPicIp != newIp) { conf.AlarmIp = newIp conf.WebPicIp = newIp } if conf.ServerId == "" { conf.ServerId = uuid.NewV4().String() if conf.AlarmPort == 0 { conf.AlarmPort = 9200 } if conf.WebPicPort == 0 { conf.WebPicPort = 6333 } if conf.ServerName == "" { conf.ServerName = newIp } if "" == newIp { newIp, _, e := util.GetLocalIP(config.Server.NetworkAdapter) if nil != e { return false, e } conf.AlarmIp = newIp conf.WebPicIp = newIp } if err := conf.Insert(); err != nil { return false, err } else { return true, nil } } else { if e := conf.Update(); e != nil { return false, e } else { if "" != newIp { go func() { //网卡可能在重启 time.Sleep(20 * time.Second) //修改国标ip IpChangePublish(newIp) }() } return false, nil } } } } // 配置时区 func TimeZone() (string, int64) { //cmd := exec.Command("/bin/sh", "-c", "echo -n $TZ") //tz, _ := cmd.Output() tz, _ := execRootCommand("readlink /etc/localtime") tzstr := string(tz) reg, err := regexp.Compile(`.*/zoneinfo/`) if err == nil { tzstr = reg.ReplaceAllString(tzstr, "") tzstr = strings.TrimSpace(tzstr) } if tzstr != "" { return strings.TrimSpace(tzstr), time.Now().Unix() } else { return "", time.Now().Unix() } zone, _ := time.Now().Zone() return zone, time.Now().Unix() } func NTPConfig() (bool, string, string) { status, server, interval := false, "", "" cron, _ := execRootCommand("crontab -l | grep ntpdate | tr -d '\n'") if task := string(cron); task != "" { status = true slice := strings.Split(task, " ") interval, server = slice[0][2:], slice[len(slice)-1] } return status, server, interval } // 设置时区 func SetTimeZone(tz string) bool { if _, err := time.LoadLocation(tz); err != nil { return false } // set env envCMD := exec.Command("/bin/sh", "-c", "TZ=%s", tz) envCMD.Run() // change permanent to the file '.profile' cleanTZ := exec.Command("/bin/sh", "-c", "sed -i '/^TZ=.*$/d' ~/.profile") cleanTZ.Run() TZ := "TZ='" + tz + "'; export TZ" appendTZCMD := fmt.Sprintf("echo \"%s\" >> ~/.profile;", TZ) appendTZ := exec.Command("/bin/sh", "-c", appendTZCMD) appendTZ.Run() execRootCommand(fmt.Sprintf("ln -sf /usr/share/zoneinfo/%s /etc/localtime", tz)) return true } // 配置系统时间 func SetLocalTime(newTime string, tz string) bool { const TimeLayout = "2006-01-02 15:04:05" _, err := time.Parse(TimeLayout, newTime) if err != nil { return false } if "" == tz { tz, _ = TimeZone() } dateCMD := fmt.Sprintf("date -s \"`date \"%s\" --date='TZ=\"%s\" %s'`\"", "+%Y-%m-%d %H:%M:%S", tz, newTime) execRootCommand(dateCMD) stopNTPCron() return true } const NTPCRONTABFILE = "/tmp/.webServer.crontab" func EnableNTPCron(server string, interval int) bool { stopNTPCron() if ip := net.ParseIP(server); ip == nil { return false } update := fmt.Sprintf("echo \"*/%d * * * * /usr/sbin/ntpdate %s\" >> %s", interval, server, NTPCRONTABFILE) execRootCommand(update) addNTPTask := fmt.Sprintf("crontab %s", NTPCRONTABFILE) execRootCommand(addNTPTask) return true } func stopNTPCron() { update := fmt.Sprintf("crontab -l | grep -v /usr/sbin/ntpdate > %s", NTPCRONTABFILE) execRootCommand(update) cleanNTPTask := fmt.Sprintf("crontab %s", NTPCRONTABFILE) execRootCommand(cleanNTPTask) } func RunNTPDate(server string) bool { if ip := net.ParseIP(server); ip == nil { return false } ntpdate := fmt.Sprintf("/usr/sbin/ntpdate %s", server) _, err := execRootCommand(ntpdate) return err == nil } func Reboot() (bool, string) { stdout, err := execRootCommand("reboot") return err == nil, string(stdout) } // * * * * * /bin/echo "$(date) Perform basic-reboot-task" >> /tmp/webserver.crontab.log;/sbin/reboot & >> /tmp/webserver.crontab.log func ReadRebootTaskInCrontab() (bool, string) { stdout, err := execRootCommand("crontab -l | grep basic-reboot-task | sed -z -r 's/([^0-9* ]+)(.+)//g'") return err == nil, string(stdout) } func CleanRebootTask() { update := fmt.Sprintf("crontab -l | grep -v basic-reboot-task > %s", NTPCRONTABFILE) execRootCommand(update) crontab := fmt.Sprintf("crontab %s", NTPCRONTABFILE) execRootCommand(crontab) } func UpdateRebootTask(task string) bool { CleanRebootTask() tasks := fmt.Sprintf("%s /bin/echo \"$(date) Perform basic-reboot-task\" >> /tmp/webserver.crontab.log;/sbin/reboot & >> /tmp/webserver.crontab.log", task) update := fmt.Sprintf("echo '%s' >> %s", tasks, NTPCRONTABFILE) execRootCommand(update) addNTPTask := fmt.Sprintf("crontab %s", NTPCRONTABFILE) _, err := execRootCommand(addNTPTask) return err == nil } const ngConfig = "/usr/local/openresty/nginx/conf/conf.d/smart-ai.conf" func GetNginxListenPort() string { _, err := os.Stat(ngConfig) if err != nil { return "" } cmdStr := fmt.Sprintf("cat %s | grep listen | awk '{printf $2}' | sed 's/;//g'", ngConfig) cmd := exec.Command("/bin/sh", "-c", cmdStr) port, err := cmd.Output() if err != nil { return "" } return string(port) } func GetNginxListenHost() string { _, err := os.Stat(ngConfig) if err != nil { return "" } cmdStr := fmt.Sprintf("cat %s | grep server_name | awk '{printf $2}' | sed 's/;//g'", ngConfig) cmd := exec.Command("/bin/sh", "-c", cmdStr) host, err := cmd.Output() if err != nil { return "" } return string(host) } // 备份nginx配置文件到tmp文件夹, 然后修改端口和域名, 使用nginx -t 验证, 成功则重启nginx, 失败则恢复原配置文件 func SetNginxConf(port, host string) bool { _, err := os.Stat(ngConfig) if err != nil { return false } // 备份 backupFilePath := "/tmp/openresty-smart-ai.conf" cmd := exec.Command("/bin/sh", "-c", "cp -f %s %s", ngConfig, backupFilePath) cmd.Run() // 修改配置文件端口 cmdStr := fmt.Sprintf("sed -i 's/listen.*/listen %s;/' %s", port, ngConfig) _, err = execRootCommand(cmdStr) // 修改配置文件端口 cmdStr = fmt.Sprintf("sed -i 's/server_name.*/server_name %s;/' %s", host, ngConfig) _, err = execRootCommand(cmdStr) _, err = execRootCommand("/usr/local/openresty/nginx/sbin/nginx -t") if err != nil { cmdStr = fmt.Sprintf("cp -f %s %s", backupFilePath, ngConfig) execRootCommand(cmdStr) return false } // 重启nginx _, err = execRootCommand("service openresty reload") return err == nil } // 设置语言 func SetLang(lang string, language string) error { // set env envCMD := exec.Command("/bin/sh", "-c", "LANG=%s", lang) envCMD.Run() // change permanent to the file '.profile' cleanTZ := exec.Command("/bin/sh", "-c", "sed -i '/^LANG=.*$/d' ~/.profile") cleanTZ.Run() LANG := "LANG='" + lang + "'; export LANG" appendTZCMD := fmt.Sprintf("echo \"%s\" >> ~/.profile;", LANG) appendTZ := exec.Command("/bin/sh", "-c", appendTZCMD) appendTZ.Run() // set env envCMD = exec.Command("/bin/sh", "-c", "LANGUAGE=%s", language) envCMD.Run() // change permanent to the file '.profile' cleanTZ = exec.Command("/bin/sh", "-c", "sed -i '/^LANGUAGE=.*$/d' ~/.profile") cleanTZ.Run() LANGUAGE := "LANGUAGE='" + lang + "'; export LANGUAGE" appendTZCMD = fmt.Sprintf("echo \"%s\" >> ~/.profile;", LANGUAGE) appendTZ = exec.Command("/bin/sh", "-c", appendTZCMD) appendTZ.Run() cmdStr := fmt.Sprintf("sed -i 's/LANG=.*/LANG=\"%s\"/' /etc/default/locale", lang) _, err := execRootCommand(cmdStr) cmdStr = fmt.Sprintf("sed -i 's/LANGUAGE=.*/LANGUAGE=\"%s\"/' /etc/default/locale", language) _, err = execRootCommand(cmdStr) return err } // 获取当前语言 func GetLang() (string, error) { content, err := execRootCommand("cat /etc/default/locale|grep LANG") if nil == err { reg, err := regexp.Compile(`LANG="(.*)"`) if nil == err { match := reg.FindSubmatch(content) if len(match) > 1 { return string(match[1]), nil } return "", nil } } return "", err } // 获取默认键盘布局 func GetDefKeyboard() (string, error) { content, err := execRootCommand("cat /etc/default/keyboard|grep XKBLAYOUT") if nil == err { reg, err := regexp.Compile(`XKBLAYOUT="(.*)"`) if nil == err { match := reg.FindSubmatch(content) if len(match) > 1 { return string(match[1]), nil } return "", nil } } return "", err } // 获取键盘布局 func GetKeyboardLayouts() (map[string]string, []sysVo.KeyBoardLayout, error) { output, err := execRootCommand("man -P cat xkeyboard-config") if nil != err { return nil, nil, err } useLine := false lines := strings.Split(string(output), "\n") keybordLayoutsLines := make([]string, 0, len(lines)) for _, item := range lines { if strings.HasPrefix(item, "LAYOUTS") { useLine = true continue } if strings.HasPrefix(item, "OPTIONS") { useLine = false } if useLine && !strings.Contains(item, "Layout") { keybordLayoutsLines = append(keybordLayoutsLines, item) } } defkeybord, err := GetDefKeyboard() keyBoardLayoutMap := make(map[string]string, 0) keyBoardLayouts := make([]sysVo.KeyBoardLayout, 0) defFound := false if defkeybord == "" { defFound = true } for _, item := range keybordLayoutsLines { reg, err := regexp.Compile(`│.+│`) if err == nil { line := reg.Find([]byte(item)) if nil != line { info := strings.Trim(string(line), "│") reg, err = regexp.Compile(`\s+`) if err == nil { info = reg.ReplaceAllString(info, " ") info := strings.TrimSpace(info) if "" != info { parts := strings.Split(info, " ") if len(parts) >= 2 { keyBoardLayoutMap[parts[0]] = strings.Join(parts[1:], " ") if len(keyBoardLayouts) < 5 && defFound || len(keyBoardLayouts) < 4 { keyBoardLayouts = append(keyBoardLayouts, sysVo.KeyBoardLayout{Id: parts[0], Name: keyBoardLayoutMap[parts[0]]}) if parts[0] == defkeybord { defFound = true } } } } } } } } return keyBoardLayoutMap, keyBoardLayouts, nil } // 设置键盘布局 func SetKeyboardLayout(layout string) error { cmdStr := fmt.Sprintf("sed -i 's/XKBLAYOUT=.*/XKBLAYOUT=\"%s\"/' /etc/default/keyboard", layout) _, err := execRootCommand(cmdStr) return err } // 关闭网络 func DownNetCard(networkAdapter string) error { cmdStr := fmt.Sprintf("ip link set %s down", networkAdapter) _, err := execRootCommand(cmdStr) return err } // 开启网络 func UpNetCard(networkAdapter string) error { _, _, err := GetLocalIP(networkAdapter) if err != nil { return errors.New("IPv4尚未配置,请配置后开启") } cmdStr := fmt.Sprintf("ip link set %s up", networkAdapter) _, err = execRootCommand(cmdStr) return err } // 获取无线网卡 func GetIwDev() ([]string, error) { content, err := execRootCommand("iw dev") if nil == err { reg, err := regexp.Compile(`Interface ([^\n]+)\n`) if nil == err { match := reg.FindAllSubmatch(content, -1) netcards := make([]string, 0) for _, item := range match { if len(item) >= 1 { netcards = append(netcards, string(item[1])) } } return netcards, nil } else { return nil, errors.New("regexp complie failed") } } return nil, errors.New("iw dev not found") } // 获取wifi网络 func ScanWifiList(netcard string) ([]iwlist.Cell, error) { return iwlist.Scan(netcard) } // 连接WIFI func ConnectWifi(fname, ssid, passwd string) error { networkConfigScript := "/opt/vasystem/script/wlanconfig" // 检查文件是否存在 if _, err := os.Stat(networkConfigScript); err != nil { return err } // # wlanconfig wlan0 Basic Basic2019 cmdStr := fmt.Sprintf("%s %s %s %s", networkConfigScript, fname, ssid, passwd) _, err := execRootCommand(cmdStr) return err //content, err := execRootCommand(fmt.Sprintf("wpa_cli -i %s add_network", fname)) //if nil != err { // return err //} //newid := strings.TrimSpace(string(content)) //reg, err := regexp.Compile(`^(\d+)$`) //if nil == err { // b := reg.MatchString(newid) // if !b { // return errors.New("WIFI加入失败") // } // ret, err := execRootCommand(fmt.Sprintf("wpa_cli -i %s set_network %s ssid '\"%s\"'", fname, newid, ssid)) // if nil != err { // return err // } // if strings.TrimSpace(string(ret)) != "OK" { // return errors.New(string(ret)) // } // ret, err = execRootCommand(fmt.Sprintf("wpa_cli -i %s set_network %s psk '\"%s\"'", fname, newid, passwd)) // if nil != err { // return err // } // if strings.TrimSpace(string(ret)) != "OK" { // return errors.New(string(ret)) // } // ret, err = execRootCommand(fmt.Sprintf("wpa_cli -i %s disconnect", fname)) // if nil != err { // return err // } // if strings.TrimSpace(string(ret)) != "OK" { // return errors.New(string(ret)) // } // ret, err = execRootCommand(fmt.Sprintf("wpa_cli -i %s select_network %s", fname, newid)) // if nil != err { // return err // } // if strings.TrimSpace(string(ret)) != "OK" { // return errors.New(string(ret)) // } // _, err = execRootCommand(fmt.Sprintf("udhcpc -i %s -q -n", fname)) // if nil != err { // return errors.New("密码好像不对哦") // } // _, err = execRootCommand(fmt.Sprintf("wpa_cli -i %s save_config", fname)) // return nil //} else { // return err //} } func ExistService(name string) string { b, err := execRootCommand(fmt.Sprintf("which %s", name)) if err != nil { return "" } return string(b) } // 配置mqtt func SetMqttConf(conf *sysVo.MqttConf) error { etcPath := "/etc/mosquitto/mosquitto.conf" pwfile := "/etc/mosquitto/pwfile" //处理是否允许匿名连接mqtt server b, _ := execRootCommand(fmt.Sprintf("cat %s|grep -E 'allow_anonymous false|allow_anonymous true'", etcPath)) if string(b) == "" { _, err := execRootCommand(fmt.Sprintf("sh -c \"echo 'allow_anonymous %s' >> %s\"", strconv.FormatBool(conf.AnonymousEnable), etcPath)) if err != nil { logger.Error("2 err:", err) return err } } else { _, err := execRootCommand(fmt.Sprintf("sed -i 's/\"%s\"/allow_anonymous \"%s\"/' %s", string(b), strconv.FormatBool(conf.AnonymousEnable), etcPath)) if err != nil { logger.Error("3 err:", err) return err } } //处理pwfile if !conf.AnonymousEnable && conf.Username != "" && conf.Password != "" { //1.在/etc/mosquitto/文件夹下生成pwfile文件 mos_user_pwd := OutputNewPassword(conf.Username, conf.Password) _, err := execRootCommand(fmt.Sprintf("echo %s > %s", mos_user_pwd, pwfile)) if err != nil { logger.Error("4 err:", err) return err } //2.修改/etc/mosquitto/mosquitto.conf中password_file的配置 es, _ := execRootCommand(fmt.Sprintf("cat %s |grep -v '#'|grep password_file|head -1", etcPath)) pwdSet := "password_file " + pwfile if string(es) == "" { _, err = execRootCommand(fmt.Sprintf("echo %s >> %s", pwdSet, etcPath)) if err != nil { logger.Error("6 err:", err) return err } } else { _, err = execRootCommand(fmt.Sprintf("sed -i 's/\"%s\"/\"%s\"/' %s", string(b), pwdSet, etcPath)) if err != nil { logger.Error("7 err:", err) return err } } } if conf.Enable { //启用mqtt server服务 _, err := execRootCommand("systemctl enable mosquitto") if err != nil { logger.Error("8 err:", err) return err } _, err = execRootCommand("systemctl restart mosquitto") if err != nil { logger.Error("9 err:", err) return err } } else { _, err := execRootCommand("systemctl disable mosquitto") if err != nil { logger.Error("10 err:", err) return err } _, err = execRootCommand("systemctl stop mosquitto") if err != nil { logger.Error("11 err:", err) return err } } return nil }