Browse Source

增加服务端口管理

master
VIVIMAN 3 years ago
parent
commit
47fec65304
  1. 0
      golang_learn/data_func/go_to_service/main.go
  2. 5
      golang_learn/data_func/go_to_windows/build.bat
  3. 265
      golang_learn/data_func/go_to_windows/main.go
  4. 22
      golang_learn/data_func/go_to_windows/main.manifest
  5. BIN
      golang_learn/data_func/go_to_windows/rsrc.syso
  6. BIN
      golang_learn/data_func/go_to_windows/serviceMonitor.ico
  7. 139
      golang_learn/data_func/go_to_windows/winService.go
  8. 1
      golang_learn/go.mod
  9. 2
      golang_learn/go.sum

0
golang_learn/data_func/go_to_windows/Main.go → golang_learn/data_func/go_to_service/main.go

5
golang_learn/data_func/go_to_windows/build.bat

@ -0,0 +1,5 @@
set GO111MODULE=on
set GOARCH=386
rsrc -manifest main.manifest -ico serviceMonitor.ico -o rsrc.syso
go build -ldflags="-s -w -H=windowsgui"
upx -9 ./serviceMonitor.exe

265
golang_learn/data_func/go_to_windows/main.go

@ -0,0 +1,265 @@
// +build windows
// +build 386
package main
import (
"fmt"
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
"github.com/lxn/win"
"golang.org/x/sys/windows"
"os/exec"
"syscall"
"time"
)
type myApp struct {
title string
msg *walk.TextEdit
mw *walk.MainWindow
}
type myService struct {
text string
serviceName string
labelState *walk.Label
btnStart *walk.PushButton
btnStop *walk.PushButton
}
var app myApp
var service1, service2, service3 myService
func init() {
app.title = "XXXX管理系统-运行监控"
service1 = myService{
text: "MySql51(MySql数据库)",
serviceName: "MySql51",
}
service2 = myService{
text: "Web服务(nginx)",
serviceName: "nginx",
}
service3 = myService{
text: "XXXX系统",
serviceName: "xxxx-server",
}
}
func main() {
_ = getWindows()
walk.App().SetProductName(app.title)
walk.App().SetOrganizationName("dwt")
_ = service1.labelState.SetText("未安装")
_ = service2.labelState.SetText("未安装")
_ = service3.labelState.SetText("未安装")
service1.btnStart.Clicked().Attach(func() {
startService(service1)
})
service1.btnStop.Clicked().Attach(func() {
stopService(service1)
})
service2.btnStart.Clicked().Attach(func() {
startService(service2)
})
service2.btnStop.Clicked().Attach(func() {
stopService(service2)
})
service3.btnStart.Clicked().Attach(func() {
startService(service3)
})
service3.btnStop.Clicked().Attach(func() {
stopService(service3)
})
go flushServiceStat(service1)
go flushServiceStat(service2)
go flushServiceStat(service3)
app.mw.Show()
app.mw.Run()
}
func setServiceState(service myService, msg string, btnStartStatus bool, btnStopStatus bool) {
_ = service.labelState.SetText(msg)
service.btnStart.SetEnabled(btnStartStatus)
service.btnStop.SetEnabled(btnStopStatus)
}
// 刷新服务状态的协程程序
func flushServiceStat(service myService) {
for {
winService, err := NewWinService(service.serviceName)
if winService == nil || err != nil {
if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
setServiceState(service, "未安装", false, false)
} else {
setServiceState(service, "服务打开失败", false, false)
}
} else {
if winService.IsStop() {
setServiceState(service, "已经停止", true, false)
} else if winService.IsRunning() {
setServiceState(service, "正在运行", false, true)
}
}
time.Sleep(time.Second)
}
}
// 启动服务
func startService(service myService) {
s, err := NewWinService(service.serviceName)
if s == nil || err != nil {
return
}
showMsg(service.serviceName + " 服务开始启动......")
err = s.StartService()
if err != nil {
showMsg(service.serviceName + " 服务启动失败!")
} else {
showMsg(service.serviceName + " 服务启动成功。")
}
}
// 停止服务
func stopService(service myService) {
s, err := NewWinService(service.serviceName)
if s == nil || err != nil {
return
}
showMsg(service.serviceName + " 服务开始停止......")
err = s.StopService()
if err != nil {
showMsg(service.serviceName + " 服务停止失败!")
} else {
showMsg(service.serviceName + " 服务停止成功。")
}
}
func showMsg(msg string) {
app.msg.AppendText(time.Now().Format("2006-01-02 15:04:05 "))
app.msg.AppendText(msg)
app.msg.AppendText("\r\n")
}
// 初始始化窗体
func getWindows() error {
icon, _ := walk.NewIconFromResourceId(3)
err := MainWindow{
Visible: false,
AssignTo: &app.mw,
Title: app.title,
Size: Size{500, 360},
Font: Font{Family: "微软雅黑", PointSize: 9},
Icon: icon,
Layout: VBox{},
Children: []Widget{
GroupBox{
Title: "基础服务状态",
Layout: Grid{Columns: 3},
Children: []Widget{
Label{Text: service1.text, MinSize: Size{220, 30}, TextColor: walk.RGB(255, 255, 0)},
Label{AssignTo: &service1.labelState, Text: "正在运行", MinSize: Size{80, 30}},
Composite{
Layout: HBox{},
MaxSize: Size{132, 30},
Children: []Widget{
PushButton{
AssignTo: &service1.btnStop,
MaxSize: Size{60, 30},
Text: "停止",
},
PushButton{
AssignTo: &service1.btnStart,
MaxSize: Size{60, 30},
Text: "启动",
},
},
},
Label{Text: service2.text},
Label{AssignTo: &service2.labelState, Text: "正在运行"},
Composite{
Layout: HBox{},
MaxSize: Size{132, 30},
Children: []Widget{
PushButton{
AssignTo: &service2.btnStop,
MaxSize: Size{60, 30},
Text: "停止",
},
PushButton{
AssignTo: &service2.btnStart,
MaxSize: Size{60, 30},
Text: "启动",
},
},
},
},
},
GroupBox{
Title: "业务服务状态",
Layout: Grid{Columns: 3},
Children: []Widget{
Label{Text: service3.text, MinSize: Size{220, 30}},
Label{AssignTo: &service3.labelState, Text: "正在运行", MinSize: Size{80, 30}},
Composite{
Layout: HBox{},
MaxSize: Size{132, 30},
Children: []Widget{
PushButton{
AssignTo: &service3.btnStop,
MaxSize: Size{60, 30},
Text: "停止",
},
PushButton{
AssignTo: &service3.btnStart,
MaxSize: Size{60, 30},
Text: "启动",
},
},
},
},
},
TextEdit{AssignTo: &app.msg, VScroll: true, ReadOnly: true},
Composite{
Layout: HBox{},
Children: []Widget{
PushButton{
MinSize: Size{160, 30},
Text: "打开windows服务管理程序",
OnClicked: func() {
c := exec.Command("cmd", "/C", "SERVICES.MSC")
c.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // 不显示命令窗口
if err := c.Start(); err != nil {
showMsg(fmt.Sprintf("打开windows服务管理程序失败, 错误信息: %s", err))
}
},
},
HSpacer{},
PushButton{
MinSize: Size{121, 30},
Text: "关闭本监控窗口",
OnClicked: func() {
walk.App().Exit(0)
},
},
},
},
},
OnSizeChanged: func() {
_ = app.mw.SetSize(walk.Size(Size{500, 360}))
},
}.Create()
winLong := win.GetWindowLong(app.mw.Handle(), win.GWL_STYLE)
// 不能调整窗口大小,禁用最大化按钮
win.SetWindowLong(app.mw.Handle(), win.GWL_STYLE, winLong & ^win.WS_SIZEBOX & ^win.WS_MAXIMIZEBOX & ^win.WS_SIZEBOX)
// 设置窗体生成在屏幕的正中间,并处理高分屏的情况
// 窗体横坐标 = ( 屏幕宽度 - 窗体宽度 ) / 2
// 窗体纵坐标 = ( 屏幕高度 - 窗体高度 ) / 2
_ = app.mw.SetX((int(win.GetSystemMetrics(0)) - app.mw.Width()) / 2 / app.mw.DPI() * 96)
_ = app.mw.SetY((int(win.GetSystemMetrics(1)) - app.mw.Height()) / 2 / app.mw.DPI() * 96)
return err
}

22
golang_learn/data_func/go_to_windows/main.manifest

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
</windowsSettings>
</application>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

BIN
golang_learn/data_func/go_to_windows/rsrc.syso

Binary file not shown.

BIN
golang_learn/data_func/go_to_windows/serviceMonitor.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

139
golang_learn/data_func/go_to_windows/winService.go

@ -0,0 +1,139 @@
package main
import (
"fmt"
"github.com/shirou/gopsutil/winservices"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
"time"
)
// 定义Service对象
type Service struct {
Name string
srv *winservices.Service
Config mgr.Config
Status winservices.ServiceStatus
}
// 得到Service信息
func (s *Service) getServiceDetail() error {
defer func() {
if err := recover(); err != nil {
return
}
}()
err := s.srv.GetServiceDetail()
if err != nil {
// 服务打开失败
return err
}
s.Name = s.srv.Name
s.Status = s.srv.Status
s.Config = s.srv.Config
return nil
}
// 启动一个服务
func (s *Service) StartService() error {
return StartService(s.Name)
}
// 停止一个服务
func (s *Service) StopService() error {
return StopService(s.Name)
}
// 服务是否已经停止
func (s *Service) IsStop() bool {
return s.Status.State == svc.Stopped
}
// 服务是否正在运行
func (s *Service) IsRunning() bool {
return s.Status.State == svc.Running
}
// 新建一个Service对象
func NewWinService(serviceName string) (*Service, error) {
winService, err := winservices.NewService(serviceName)
if err != nil {
return nil, err
}
result := &Service{
Name: serviceName,
srv: winService,
}
err = result.getServiceDetail()
return result, err
}
// 得到Service信息
func GetServiceInfo(serviceName string) (*winservices.Service, error) {
defer func() {
if err := recover(); err != nil {
return
}
}()
newservice, _ := winservices.NewService(serviceName)
err := newservice.GetServiceDetail()
if err != nil {
fmt.Println(serviceName, "服务打开失败!")
return nil, err
}
return newservice, nil
}
// 启动一个服务
func StartService(name string) error {
m, err := mgr.Connect()
if err != nil {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if err != nil {
return fmt.Errorf("could not access service: %v", err)
}
defer s.Close()
err = s.Start("is", "manual-started")
if err != nil {
return fmt.Errorf("could not start service: %v", err)
}
return nil
}
// 停止一个服务
func StopService(name string) error {
return ControlService(name, svc.Stop, svc.Stopped)
}
// 改一个服务状态,
func ControlService(name string, c svc.Cmd, to svc.State) error {
m, err := mgr.Connect()
if err != nil {
return err
}
defer m.Disconnect()
s, err := m.OpenService(name)
if err != nil {
return fmt.Errorf("could not access service: %v", err)
}
defer s.Close()
status, err := s.Control(c)
if err != nil {
return fmt.Errorf("could not send control=%d: %v", c, err)
}
timeout := time.Now().Add(10 * time.Second)
for status.State != to {
if timeout.Before(time.Now()) {
return fmt.Errorf("timeout waiting for service to go to state=%d", to)
}
time.Sleep(300 * time.Millisecond)
status, err = s.Query()
if err != nil {
return fmt.Errorf("could not retrieve service status: %v", err)
}
}
return nil
}

1
golang_learn/go.mod

@ -23,6 +23,7 @@ require (
github.com/mattn/go-oci8 v0.1.1
github.com/mattn/go-sqlite3 v1.14.8
github.com/russross/blackfriday v1.6.0
github.com/shirou/gopsutil v2.20.4+incompatible
github.com/spf13/viper v1.8.1
github.com/yeka/zip v0.0.0-20180914125537-d046722c6feb
golang.org/x/exp/errors v0.0.0-20210715201039-d37aa40e8013

2
golang_learn/go.sum

@ -266,6 +266,8 @@ github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3V
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil v2.20.4+incompatible h1:cMT4rxS55zx9NVUnCkrmXCsEB/RNfG9SwHY9evtX8Ng=
github.com/shirou/gopsutil v2.20.4+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=

Loading…
Cancel
Save