diff --git a/Configuration_file.yml b/Configuration_file.yml new file mode 100644 index 0000000000000000000000000000000000000000..422671515cdd85dc7e38354a620fcf9566420cb8 --- /dev/null +++ b/Configuration_file.yml @@ -0,0 +1 @@ +//配置文件 diff --git a/DB_OSInspection b/DB_OSInspection new file mode 100644 index 0000000000000000000000000000000000000000..04046acf81f03a1fcefb5b959cba24f2a3aa13dc Binary files /dev/null and b/DB_OSInspection differ diff --git a/DB_OSInspection.exe b/DB_OSInspection.exe new file mode 100644 index 0000000000000000000000000000000000000000..51697579b1e0cf42153d8b3cbcbbb3bd64310785 Binary files /dev/null and b/DB_OSInspection.exe differ diff --git a/Global/Global.go b/Global/Global.go new file mode 100644 index 0000000000000000000000000000000000000000..2476a413003230aa6e228616bc73ce5e41cc067a --- /dev/null +++ b/Global/Global.go @@ -0,0 +1,7 @@ +package Global + +import "database/sql" + +var Table_index_inspection_result = make(map[string]string) + +var DB *sql.DB diff --git a/Index/Index_columns_Inspection.go b/Index/Index_columns_Inspection.go index 34238dffddf4802265cc29a2a73affd334a5e61e..3abbd543c931368f8fd45f12925d23c3afefbd3e 100644 --- a/Index/Index_columns_Inspection.go +++ b/Index/Index_columns_Inspection.go @@ -1,8 +1,10 @@ package Index import ( - "database/sql" + "DB_OSInspection/Global" "fmt" + + "github.com/gookit/color" ) type User struct { @@ -10,12 +12,19 @@ type User struct { TABLE_NAME string CHARACTER_SET_NAME string Field_Type string - INDEX_COUNT int } -func Index_redundant_Inspection(db *sql.DB) { +var ( + // color + Green = color.Green.Render + Yellow = color.Yellow.Render + Red = color.Red.Render + Completed = color.S256(255, 27) +) + +func Index_redundant_Inspection() { sqlStr := "SELECT table_schema,table_name,redundant_index_name,redundant_index_columns FROM sys.schema_redundant_indexes GROUP BY table_schema,table_name,redundant_index_name,redundant_index_columns;" - counts, err := db.Query(sqlStr) + counts, err := Global.DB.Query(sqlStr) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -29,7 +38,7 @@ func Index_redundant_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【redundant_index_name: %s】【redundant_index_columns:%s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.Field_Type) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【redundant_index_name: %s】【redundant_index_columns:%s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.Field_Type)) for counts.Next() { var user User count += 1 @@ -37,17 +46,20 @@ func Index_redundant_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【redundant_index_name: %s】【redundant_index_columns:%s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.Field_Type) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【redundant_index_name: %s】【redundant_index_columns:%s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.Field_Type)) } } else { - fmt.Println("————————————————————【没有重复索引的表】—————————————————") + color.BgGreen.Println("————————————————————【没有重复索引的表】————————————————") + } - fmt.Printf("—————————————————↑重复索引表巡检完毕↑————————————————\n\n") + Completed.Printf("———————————————————↑重复索引表巡检完毕↑——————————————————") + fmt.Println(" \n ") + } -func Index_columns_Inspection(db *sql.DB) { +func Index_columns_Inspection() { var index_columns int = 5 sqlStr := "SELECT s.table_schema, s.table_name,s.index_name,s.column_name FROM information_schema.STATISTICS s,(SELECT table_name,index_name,count(*)FROM information_schema.STATISTICS WHERE table_schema NOT IN ( 'information_schema', 'performance_schema', 'mysql', 'sys' ) GROUP BY table_name,index_name HAVING count(*)> ?) t WHERE s.table_name = t.table_name AND s.index_name = t.index_name;" - counts, err := db.Query(sqlStr, index_columns) + counts, err := Global.DB.Query(sqlStr, index_columns) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -61,7 +73,7 @@ func Index_columns_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】【column_name:%s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.Field_Type) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】【column_name:%s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.Field_Type)) for counts.Next() { var user User count += 1 @@ -69,17 +81,20 @@ func Index_columns_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】【column_name:%s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.Field_Type) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】【column_name:%s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.Field_Type)) } } else { - fmt.Printf("————————————————————【没有索引列超%d过个的索引】———————————————\n", index_columns) + color.BgGreen.Printf("—————————————————【没有索引列超%d过个的索引】————————————", index_columns) + fmt.Println(" \n ") + } - fmt.Printf("—————————————————↑索引列超过%d个的索引巡检完毕↑————————————————\n\n", index_columns) + Completed.Printf("——————————————↑索引列超过%d个的索引巡检完毕↑————————————", index_columns) + fmt.Println(" \n ") } -func Index_unused_Inspection(db *sql.DB) { +func Index_unused_Inspection() { sqlStr := "select * from sys.schema_unused_indexes;" - counts, err := db.Query(sqlStr) + counts, err := Global.DB.Query(sqlStr) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -93,7 +108,7 @@ func Index_unused_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME)) for counts.Next() { var user User count += 1 @@ -101,11 +116,12 @@ func Index_unused_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【index_name: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME)) } } else { - fmt.Printf("————————————————————【没有无用的索引】———————————————\n") + color.BgGreen.Printf("——————————————————————【没有无用的索引】—————————————————\n") } - fmt.Printf("—————————————————↑无用的索引巡检完毕↑————————————————\n\n") + Completed.Printf("———————————————————↑无用的索引巡检完毕↑——————————————————") + fmt.Println(" \n ") } diff --git a/Inspection/Inspection.go b/Inspection/Inspection.go new file mode 100644 index 0000000000000000000000000000000000000000..2e9f1371d327bfeaa4809eaef5e4a91d9a640031 --- /dev/null +++ b/Inspection/Inspection.go @@ -0,0 +1,30 @@ +package Inspection + +import ( + "DB_OSInspection/Global" + "fmt" + "strconv" + + "github.com/gookit/color" +) + +var ( + // color + Yellow = color.Yellow.Render + Cyan = color.Cyan.Render + LightGreen = color.Style{color.Green, color.OpBold}.Render +) + +func Inspection() { + fmt.Println("——————————————————提醒和建议[正在开发中...]—————————————————————") + for k, v := range Global.Table_index_inspection_result { + i, _ := strconv.Atoi(v) + if i > 10 { + fmt.Printf("——您的表:%s索引值太多——", LightGreen(k)) + + } + + } + fmt.Println(" \n ") + fmt.Println("——————————————————提醒和建议(完)—————————————————————") +} diff --git a/Menu/Menu.go b/Menu/Menu.go index 250dda1b34405a075b20c840e048c47859dfb113..efe9df529eb95daf674f0f02753a8d510e915fd9 100644 --- a/Menu/Menu.go +++ b/Menu/Menu.go @@ -2,63 +2,68 @@ package Menu import ( "DB_OSInspection/Index" + "DB_OSInspection/Inspection" + "DB_OSInspection/Monitor" "DB_OSInspection/Privileges" "DB_OSInspection/Status" "DB_OSInspection/Table" "DB_OSInspection/User" "DB_OSInspection/Variables" - "database/sql" "fmt" ) -func Menu(db *sql.DB, m string) { +func Menu(m string) { //选择模式:all全部巡检、table只巡检表、index只巡检索引、variables只巡检重要参数、status只巡检重要状态、user只巡检用户、privileges只巡检权限 switch m { case "all": //表巡检 - Table.Table_Data_Size_Inspection(db) - Table.Table_Index_Size_Inspection(db) - Table.Table_fragment_Size_Inspection(db) - Table.Table_rows_Size_Inspection(db) - Table.Table_chaset_Inspection(db) - Table.Table_big_columns_Inspection(db) - Table.Table_long_varchar_Inspection(db) - Table.Table_no_index_Inspection(db) + Table.Table_Data_Size_Inspection() + Table.Table_Index_Size_Inspection() + Table.Table_fragment_Size_Inspection() + Table.Table_rows_Size_Inspection() + Table.Table_chaset_Inspection() + Table.Table_big_columns_Inspection() + Table.Table_long_varchar_Inspection() + Table.Table_no_index_Inspection() //索引巡检 - Index.Index_redundant_Inspection(db) - Index.Index_columns_Inspection(db) - Index.Index_unused_Inspection(db) + Index.Index_redundant_Inspection() + Index.Index_columns_Inspection() + Index.Index_unused_Inspection() //参数巡检 - Variables.Variables_Inspection(db) + Variables.Variables_Inspection() //状态巡检 - Status.Important_status_Inspection(db) + Status.Important_status_Inspection() //用户巡检 - User.User_nopass_Inspection(db) + User.User_nopass_Inspection() //权限巡检 - Privileges.Privileges_Inspection(db) - Privileges.User_Privileges_Inspection(db) + Privileges.Privileges_Inspection() + Privileges.User_Privileges_Inspection() + Inspection.Inspection() case "table": - Table.Table_Data_Size_Inspection(db) - Table.Table_Index_Size_Inspection(db) - Table.Table_fragment_Size_Inspection(db) - Table.Table_rows_Size_Inspection(db) - Table.Table_chaset_Inspection(db) - Table.Table_big_columns_Inspection(db) - Table.Table_long_varchar_Inspection(db) - Table.Table_no_index_Inspection(db) + Table.Table_Data_Size_Inspection() + Table.Table_Index_Size_Inspection() + Table.Table_fragment_Size_Inspection() + Table.Table_rows_Size_Inspection() + Table.Table_chaset_Inspection() + Table.Table_big_columns_Inspection() + Table.Table_long_varchar_Inspection() + Table.Table_no_index_Inspection() case "index": - Index.Index_redundant_Inspection(db) - Index.Index_columns_Inspection(db) - Index.Index_unused_Inspection(db) + Index.Index_redundant_Inspection() + Index.Index_columns_Inspection() + Index.Index_unused_Inspection() case "variables": - Variables.Variables_Inspection(db) + Variables.Variables_Inspection() case "status": - Status.Important_status_Inspection(db) + Status.Important_status_Inspection() case "user": - User.User_nopass_Inspection(db) + User.User_nopass_Inspection() case "privileges": - Privileges.Privileges_Inspection(db) - Privileges.User_Privileges_Inspection(db) + Privileges.Privileges_Inspection() + Privileges.User_Privileges_Inspection() + case "monitor": + Monitor.DB_monitor() + default: fmt.Println("你未选择模式") } diff --git a/Monitor/DB_Monitor.go b/Monitor/DB_Monitor.go new file mode 100644 index 0000000000000000000000000000000000000000..59922ff67dbf0a621867a26dcab6626c7a949114 --- /dev/null +++ b/Monitor/DB_Monitor.go @@ -0,0 +1,207 @@ +package Monitor + +import ( + "DB_OSInspection/Global" + "bytes" + "fmt" + "io" + "log" + "os" + "os/signal" + "strconv" + "strings" + "time" + + "github.com/gookit/color" +) + +var ( + // color + Yellow = color.Yellow.Render + Cyan = color.Cyan.Render + LightGreen = color.Style{color.Green, color.OpBold}.Render +) +var ( + logfile string + cstZone = time.FixedZone("CST", 8*3600) +) + +func DB_monitor() { + color.Redln("您现在进入的是MySQL数据库监测,将会实时输出对数据库的操作!") + if !isRoot() { + log.Fatalln("run as a user with root! Thx:)") + } + defer func() { + if err := cleanGenerakLog(); err != nil { + log.Printf("cleanGenerakLog error: %s \n", err) + } + if err := closeLogRaw(); err != nil { + log.Printf("closeLogRaw error: %s \n", err) + } + if err := Global.DB.Close(); err != nil { + log.Printf("close database connection error: %s \n", err) + } + }() + if err := setMySQLLogOutput(); err != nil { + log.Fatalf("setMySQLLogOutput error: %s", err) + } + if err := openLogRaw(); err != nil { + log.Fatalf("openLogRaw error: %s", err) + } + watchdog() +} + +func isRoot() bool { + //判断是否是超级用户权限 + return os.Geteuid() == 0 +} +func cleanGenerakLog() error { + //关闭MySQL的 general_log,如果存在就清空 + if _, err := Global.DB.Exec("SET GLOBAL general_log='OFF'"); err != nil { + return err + } + if logfile != "" { + return os.Truncate(logfile, 0) + } + return nil +} +func closeLogRaw() error { + // sett log_raw=0 + if _, err := Global.DB.Exec("SET GLOBAL log_raw = 'OFF'"); err != nil { + return err + } + return nil +} + +type mysqlVariable struct { + Name string `sql:"Variable_name"` + Value string `sql:"Value"` +} + +func setMySQLLogOutput() error { + variable := mysqlVariable{} + row := Global.DB.QueryRow("SHOW VARIABLES LIKE 'general_log_file'") + if err := row.Scan(&variable.Name, &variable.Value); err != nil { + return err + } + if variable.Name == "general_log_file" { + logfile = variable.Value + } + + if _, err := Global.DB.Exec("SET GLOBAL log_output = 'FILE'"); err != nil { + return err + } + if _, err := Global.DB.Exec("SET GLOBAL general_log='ON'"); err != nil { + return err + } + return nil +} + +func catMySQLVersion() (string, error) { + var version string + row := Global.DB.QueryRow("SELECT version();") + if err := row.Scan(&version); err != nil { + return "", err + } + return version, nil +} +func openLogRaw() error { + version, err := catMySQLVersion() + if err != nil { + return err + } + vs := strings.Split(version, ".") + if len(vs) < 1 { + return fmt.Errorf("mysql version '%s' ", version) + } + + if v, err := strconv.Atoi(vs[0]); err != nil { + return err + } else if v < 8 { + return nil + } + // sett log_raw=1 + if _, err := Global.DB.Exec("SET GLOBAL log_raw = 'ON'"); err != nil { + return err + } + return nil +} +func watchdog() { + var f *os.File + + if logfile == "" { + log.Fatalln("general_log_file was empty :(") + } + f, err := os.Open(logfile) + if err != nil { + log.Fatalf("Open '%s' error: %s", logfile, err) + } + defer f.Close() + // 指向文件尾部 + _, err = f.Seek(0, 2) + if err != nil { + log.Fatalf("'%s' File.Seek(0,2) error: %s", logfile, err) + } + + handle := func(line string) { + if strings.Contains(line, "Execute") || strings.Contains(line, "Query") { + lines := strings.Split(line, "\t") + t, err := str2Time(lines[0], "2006-01-02T15:04:05Z") + if err == nil { + lines[0] = t.In(cstZone).Format("15:04:05") + } + c := strings.Split(strings.TrimSpace(lines[1]), " ")[1] + fmt.Printf("%s -> [%s] `%s`\n", Yellow(c), Cyan(lines[0]), LightGreen(lines[2])) + } + } + + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt) +LOOP: + + for { + select { + case <-quit: + break LOOP + default: + if err := linePrinter(f, handle); err != nil { + log.Printf("linePrinter error: %s \n", err) + break LOOP + } + time.Sleep(time.Millisecond * 550) + } + } +} + +func linePrinter(r io.Reader, call func(string)) error { + buf := make([]byte, 32*1024) + lineSep := []byte{'\n'} + + for { + c, err := r.Read(buf) + if c == 0 { + return nil + } + for _, line := range bytes.Split(buf[:c], lineSep) { + call(string(line)) + } + switch { + case err == io.EOF: + return nil + case err != nil: + return err + } + } +} + +func str2Time(timestr string, format string) (time.Time, error) { + var ( + t time.Time + err error + ) + t, err = time.Parse(format, timestr) + if err != nil { + return t, err + } + return t, nil +} diff --git a/Privileges/Privileges_Inspection.go b/Privileges/Privileges_Inspection.go index 75d6fbea0d17c1eff23449e82abc6c59070668ec..a2fa8b3e484c746c9b3e4c5d889775e7be783e9a 100644 --- a/Privileges/Privileges_Inspection.go +++ b/Privileges/Privileges_Inspection.go @@ -1,26 +1,30 @@ package Privileges import ( - "database/sql" + "DB_OSInspection/Global" "fmt" + + "github.com/gookit/color" ) type User struct { - TABLE_SCHEMA string - TABLE_NAME string - CHARACTER_SET_NAME string - Field_Type string - INDEX_COUNT int - SIZE_IN_GB float32 + TABLE_SCHEMA string + TABLE_NAME string } -// var user_user [100]string -// var user_usera_slice []string = user_user[:] -var user_usera_slice = make([]string, 0, 3) +var ( + // color + Green = color.Green.Render + Yellow = color.Yellow.Render + Red = color.Red.Render + Completed = color.S256(255, 27) +) + +var user_usera_slice = make([]string, 0, 30) -func Privileges_Inspection(db *sql.DB) { +func Privileges_Inspection() { sqlStr := "select user,host from mysql.user where user not in ('mysql.session','mysql.sys','mysql.infoschema');" - counts, err := db.Query(sqlStr) + counts, err := Global.DB.Query(sqlStr) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -36,22 +40,23 @@ func Privileges_Inspection(db *sql.DB) { panic(err.Error()) } count += 1 - fmt.Printf("%d.【USER: %s】【HOST: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("%d.【USER: %s】【HOST: %s】\n", count, Green(user.TABLE_SCHEMA), Red(user.TABLE_NAME)) } } -func User_Privileges_Inspection(db *sql.DB) { +func User_Privileges_Inspection() { var user User for j := 0; j < len(user_usera_slice); j++ { values := user_usera_slice[j] sqlStr := "show grants for" + "'" + values + "'" - err := db.QueryRow(sqlStr).Scan(&user.TABLE_SCHEMA) + err := Global.DB.QueryRow(sqlStr).Scan(&user.TABLE_SCHEMA) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } - fmt.Printf("【name: %s\n", user.TABLE_SCHEMA) + fmt.Printf("【grants: %s\n】", user.TABLE_SCHEMA) } - fmt.Printf("——————————————————↑用户权限巡检完毕↑—————————————————————\n\n") + Completed.Printf("——————————————————↑用户权限巡检完毕↑—————————————————————") + fmt.Println(" \n ") } diff --git a/README.md b/README.md index 029b137033f0a3fb24f7dcf990e109a485be53f3..4758b02356d9f1d72d77e06e5fed25fab58e9b54 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,18 @@ DB OSInspection 数据库巡检工具,实现对数据库一键巡检,对实 一秒了解数据库 ## 快速上手 ```go -./DB_OSInspection -u 用户名 -p 密码 +Windows环境下可直接使用,不能保存巡检结果 +./DB_OSInspection -u 用户名 -p 密码 + +#再Linux环境下保存巡检结果可以用 + ./DB_OSInspection -u 用户名 -p 密码 >err.log + +#监测模式 +./DB_OSInspection -u 用户名 -p 密码 -m monitor ``` 即可实现全表巡检 ### 参数解析 -所有输入后面都需要跟空格,否则会错误 +**所有输入后面都需要跟空格,否则会错误** - -u 输入用户名 默认为root - -p @@ -25,12 +32,14 @@ DB OSInspection 数据库巡检工具,实现对数据库一键巡检,对实 - -P 输入IP号和端口号 默认为localhost:3306 - -m -模式选择all全部巡检、table只巡检表、index只巡检索引、variables只巡检重要参数、status只巡检重要状态、user只巡检用户、privileges只巡检权限 +模式默认选择all全部巡检、table只巡检表、index只巡检索引、variables只巡检重要参数、status只巡检重要状态、user只巡检用户、privileges只巡检权限、monitor实现数据库监控 - -v 输出版本号 - -h 输出帮助 ## 已实现功能 +### 实现数据库监控可实时输出 +-m 选择monitor 模式即可 ### 实现表巡检 - 大小超过10G的表 - 索引超过6个的表 diff --git a/Status/Status_Inspection.go b/Status/Status_Inspection.go index 35e761fb60cac0acfade119df5caa3a09d5f66dd..ad9311521327207be6fd025ed52c210fa826001d 100644 --- a/Status/Status_Inspection.go +++ b/Status/Status_Inspection.go @@ -1,31 +1,36 @@ package Status import ( - "database/sql" + "DB_OSInspection/Global" "fmt" + + "github.com/gookit/color" ) type User struct { - TABLE_SCHEMA string - TABLE_NAME string - CHARACTER_SET_NAME string - Field_Type string - INDEX_COUNT int - SIZE_IN_GB float32 + TABLE_SCHEMA string + TABLE_NAME string } -func Important_status_Inspection(db *sql.DB) { +var ( + // color + Green = color.Green.Render + Red = color.Red.Render + Completed = color.S256(255, 27) +) + +func Important_status_Inspection() { var status_list = [...]string{"Uptime", "Opened_files", "Opened_table_definitions", "Opened_tables", "Max_used_connections", "Threads_created", "Threads_connected", "Aborted_connects", "Aborted_clients", "Table_locks_waited", "Innodb_buffer_pool_wait_free", "Innodb_log_waits", "Innodb_row_lock_waits", "Innodb_row_lock_time_avg", "Binlog_cache_disk_use", "Created_tmp_disk_tables"} for j := 0; j < len(status_list); j++ { var user User values := status_list[j] sqlStr := "show global status like" + "'%" + values + "'" - err := db.QueryRow(sqlStr).Scan(&user.TABLE_SCHEMA, &user.TABLE_NAME) + err := Global.DB.QueryRow(sqlStr).Scan(&user.TABLE_SCHEMA, &user.TABLE_NAME) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } - fmt.Printf("【name: %s】【value: %s】\n", user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("【name: %s】【value: %s】\n", Green(user.TABLE_SCHEMA), Red(user.TABLE_NAME)) } - fmt.Printf("——————————————————↑重要状态巡检完毕↑—————————————————————\n\n") - + Completed.Printf("——————————————————↑重要状态巡检完毕↑—————————————————————") + fmt.Println(" \n ") } diff --git a/Table/Table_Inspection.go b/Table/Table_Inspection.go index 43f02d4a8741d33e63ba716d299d838de0b9f1bb..a76a82e37e8965e8415ff08367d1ce26404ba1a6 100644 --- a/Table/Table_Inspection.go +++ b/Table/Table_Inspection.go @@ -1,8 +1,10 @@ package Table import ( - "database/sql" + "DB_OSInspection/Global" "fmt" + + "github.com/gookit/color" ) type User struct { @@ -10,19 +12,25 @@ type User struct { TABLE_NAME string CHARACTER_SET_NAME string Field_Type string - INDEX_COUNT int - SIZE_IN_GB float32 + INDEX_COUNT string + SIZE_IN_GB string } -func Table_Data_Size_Inspection(db *sql.DB) { +var ( + // color + Green = color.Green.Render + Yellow = color.Yellow.Render + Red = color.Red.Render + Completed = color.S256(255, 27) +) +func Table_Data_Size_Inspection() { var totalSize int64 = 10737418240 sqlStr := "SELECT TABLE_SCHEMA, TABLE_NAME, ROUND((DATA_LENGTH + INDEX_LENGTH)/1024/1024/1024, 4) AS SIZE_IN_GB FROM INFORMATION_SCHEMA.TABLES WHERE DATA_LENGTH + INDEX_LENGTH > ? ORDER BY SIZE_IN_GB DESC;" - counts, err := db.Query(sqlStr, totalSize) + counts, err := Global.DB.Query(sqlStr, totalSize) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } - defer counts.Close() count := 0 if counts.Next() { @@ -32,7 +40,7 @@ func Table_Data_Size_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【SIZE_IN_GB: %f】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.SIZE_IN_GB) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【SIZE_IN_GB: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) for counts.Next() { var user User count += 1 @@ -40,18 +48,19 @@ func Table_Data_Size_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【SIZE_IN_GB: %f】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.SIZE_IN_GB) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【SIZE_IN_GB: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) } } else { - fmt.Println("————————————————————【没有超过10G的表】—————————————————") + color.BgGreen.Println("————————————————————【没有超过10G的表】—————————————————") } - fmt.Printf("—————————————————↑大于%dG数据表巡检完毕↑————————————————\n\n", totalSize/1024/1024/1024) + Completed.Printf("—————————————————↑大于%dG数据表巡检完毕↑————————————————", totalSize/1024/1024/1024) + fmt.Println(" \n ") } -func Table_Index_Size_Inspection(db *sql.DB) { +func Table_Index_Size_Inspection() { var indexSize int = 6 sqlStr := "SELECT TABLE_SCHEMA, TABLE_NAME, COUNT(*) AS INDEX_COUNT FROM INFORMATION_SCHEMA.STATISTICS GROUP BY TABLE_SCHEMA, TABLE_NAME HAVING INDEX_COUNT > ?;" - counts, err := db.Query(sqlStr, indexSize) + counts, err := Global.DB.Query(sqlStr, indexSize) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -63,30 +72,35 @@ func Table_Index_Size_Inspection(db *sql.DB) { var user User count += 1 err := counts.Scan(&user.TABLE_SCHEMA, &user.TABLE_NAME, &user.INDEX_COUNT) + //赋值给全局结构体 + Global.Table_index_inspection_result[user.TABLE_NAME] = user.INDEX_COUNT if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【INDEX_COUNT: %d】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.INDEX_COUNT) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【INDEX_COUNT: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) for counts.Next() { var user User count += 1 err := counts.Scan(&user.TABLE_SCHEMA, &user.TABLE_NAME, &user.INDEX_COUNT) + //赋值给全局结构体 + Global.Table_index_inspection_result[user.TABLE_NAME] = user.INDEX_COUNT if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【INDEX_COUNT: %d】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.INDEX_COUNT) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【INDEX_COUNT: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) } } else { - fmt.Println("————————————————————【没有超过6个索引的表】——————————————————") + color.BgGreen.Println("————————————————————【没有超过6个索引的表】——————————————————") } - fmt.Printf("—————————————————↑超过%d个索引表巡检完毕↑————————————————\n\n", indexSize) + Completed.Printf("—————————————————↑超过%d个索引表巡检完毕↑————————————————", indexSize) + fmt.Println(" \n ") } -func Table_fragment_Size_Inspection(db *sql.DB) { +func Table_fragment_Size_Inspection() { var fragmentSize float32 = 0.5 sqlStr := "SELECT TABLE_SCHEMA,TABLE_NAME,1- ( TABLE_ROWS * AVG_ROW_LENGTH )/(DATA_LENGTH + INDEX_LENGTH + DATA_FREE ) AS `fragment_pct` FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ( 'information_schema', 'mysql', 'performance_schema', 'sys' ) AND (1- ( TABLE_ROWS * AVG_ROW_LENGTH )/(DATA_LENGTH + INDEX_LENGTH + DATA_FREE )) > ? AND ( DATA_LENGTH + INDEX_LENGTH + DATA_FREE ) > 1024 * 1024 * 1024;" - counts, err := db.Query(sqlStr, fragmentSize) + counts, err := Global.DB.Query(sqlStr, fragmentSize) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -99,7 +113,7 @@ func Table_fragment_Size_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【FRAGMENT_PCT: %f】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.SIZE_IN_GB) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【FRAGMENT_PCT: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) for counts.Next() { var user User count += 1 @@ -107,19 +121,20 @@ func Table_fragment_Size_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【FRAGMENT_PCT: %f】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.SIZE_IN_GB) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【FRAGMENT_PCT: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) } } else { - fmt.Println("—————————————————【没有超过50%碎片率的表】——————————————") + color.BgGreen.Println("—————————————————【没有超过50%碎片率的表】——————————————") } - fmt.Printf("———————————————↑超过%f%%个碎片率表巡检完毕↑———————————————\n\n", fragmentSize*100) + Completed.Printf("————————————↑超过%f%%碎片率表巡检完毕↑————————————", fragmentSize*100) + fmt.Println(" \n ") } -func Table_rows_Size_Inspection(db *sql.DB) { +func Table_rows_Size_Inspection() { var rowsSize int32 = 10000000 sqlStr := "SELECT table_schema,table_name,table_rows FROM information_schema.TABLES WHERE table_schema NOT IN ( 'information_schema', 'mysql', 'performance_schema', 'sys' )AND table_rows > ? ORDER BY table_rows DESC;" - counts, err := db.Query(sqlStr, rowsSize) + counts, err := Global.DB.Query(sqlStr, rowsSize) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -133,7 +148,7 @@ func Table_rows_Size_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【TABLE_ROWS: %f】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.SIZE_IN_GB) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【TABLE_ROWS: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) for counts.Next() { var user User count += 1 @@ -141,19 +156,20 @@ func Table_rows_Size_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【TABLE_ROWS: %f】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.SIZE_IN_GB) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【TABLE_ROWS: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.INDEX_COUNT)) } } else { - fmt.Println("——————————————————【没有超过1千万行的表】————————————————") + color.BgGreen.Println("——————————————————【没有超过1千万行的表】————————————————") } - fmt.Printf("—————————————————↑超过%d万行的表巡检完毕↑————————————————\n\n", rowsSize/10000) + Completed.Printf("————————————————↑超过%d万行的表巡检完毕↑———————————————", rowsSize/10000) + fmt.Println(" \n ") } -func Table_chaset_Inspection(db *sql.DB) { +func Table_chaset_Inspection() { var default_charset string = "utf8mb4" sqlStr := "SELECT DISTINCT TABLE_SCHEMA,TABLE_NAME,CCSA.CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.TABLES T JOIN INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY CCSA ON T.TABLE_COLLATION = CCSA.COLLATION_NAME WHERE CCSA.CHARACTER_SET_NAME <> ? ORDER BY TABLE_SCHEMA,TABLE_NAME;" - counts, err := db.Query(sqlStr, default_charset) + counts, err := Global.DB.Query(sqlStr, default_charset) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -167,7 +183,7 @@ func Table_chaset_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【CHARACTER_SET_NAME: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【CHARACTER_SET_NAME: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME)) for counts.Next() { var user User count += 1 @@ -175,17 +191,18 @@ func Table_chaset_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【CHARACTER_SET_NAME: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【CHARACTER_SET_NAME: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME)) } } else { - fmt.Println("————————————————————【没有非utf8mb4的表】————————————————") + color.BgGreen.Println("————————————————————【没有非utf8mb4的表】————————————————") } - fmt.Printf("—————————————————↑非字符集%s的表巡检完毕↑————————————————\n\n", default_charset) + Completed.Printf("———————————————↑非字符集%s的表巡检完毕↑—————————————", default_charset) + fmt.Println(" \n ") } -func Table_big_columns_Inspection(db *sql.DB) { +func Table_big_columns_Inspection() { sqlStr := "SELECT table_schema,table_name,column_name,data_type FROM information_schema.COLUMNS WHERE data_type IN ( 'blob', 'clob', 'text', 'medium text', 'long text' ) AND table_schema NOT IN ('information_schema','performance_schema','mysql','sys');" - counts, err := db.Query(sqlStr) + counts, err := Global.DB.Query(sqlStr) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -198,7 +215,7 @@ func Table_big_columns_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【DATA_TYPE : %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.Field_Type) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【DATA_TYPE : %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.Field_Type)) for counts.Next() { var user User count += 1 @@ -206,19 +223,20 @@ func Table_big_columns_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【DATA_TYPE : %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.Field_Type) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【DATA_TYPE : %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.Field_Type)) } } else { - fmt.Println("————————————————————【没有大字段的表】———————————————————") + color.BgGreen.Println("————————————————————【没有大字段的表】———————————————————") } - fmt.Printf("——————————————————↑大字段的表巡检完毕↑————————————————————\n\n") + Completed.Printf("——————————————————↑大字段的表巡检完毕↑————————————————————") + fmt.Println(" \n ") } -func Table_long_varchar_Inspection(db *sql.DB) { +func Table_long_varchar_Inspection() { var long_varchar int = 500 sqlStr := "SELECT table_schema,table_name,column_name,CHARACTER_MAXIMUM_LENGTH FROM information_schema.COLUMNS WHERE DATA_TYPE = 'varchar' AND CHARACTER_MAXIMUM_LENGTH > ? AND table_schema NOT IN ( 'information_schema', 'performance_schema', 'mysql', 'sys' );" - counts, err := db.Query(sqlStr, long_varchar) + counts, err := Global.DB.Query(sqlStr, long_varchar) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -232,7 +250,7 @@ func Table_long_varchar_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【CHARACTER_MAXIMUM_LENGTH : %d】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.INDEX_COUNT) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【CHARACTER_MAXIMUM_LENGTH : %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.INDEX_COUNT)) for counts.Next() { var user User count += 1 @@ -240,19 +258,19 @@ func Table_long_varchar_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【CHARACTER_MAXIMUM_LENGTH : %d】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME, user.CHARACTER_SET_NAME, user.INDEX_COUNT) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】【COLUMN_NAME: %s】【CHARACTER_MAXIMUM_LENGTH : %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME), Red(user.CHARACTER_SET_NAME), Red(user.INDEX_COUNT)) } } else { - fmt.Println("————————————【没有varchar定义长度超过500的表】———————————") + color.BgGreen.Println("————————————【没有Varchar定义长度超过500的表】———————————") } - fmt.Printf("————————————————↑varchar定义长度超过%d的表↑——————————————\n\n", long_varchar) - + Completed.Printf("————————————————↑Varchar定义长度超过%d的表↑——————————————", long_varchar) + fmt.Println(" \n ") } -func Table_no_index_Inspection(db *sql.DB) { +func Table_no_index_Inspection() { sqlStr := "SELECT t.table_schema,t.table_name FROM information_schema.TABLES AS t LEFT JOIN ( SELECT DISTINCT table_schema, table_name FROM information_schema.`KEY_COLUMN_USAGE` ) AS kt ON kt.table_schema = t.table_schema AND kt.table_name = t.table_name WHERE t.table_schema NOT IN ( 'mysql', 'information_schema', 'performance_schema', 'sys' ) AND kt.table_name IS NULL;" - counts, err := db.Query(sqlStr) + counts, err := Global.DB.Query(sqlStr) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -266,7 +284,7 @@ func Table_no_index_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME)) for counts.Next() { var user User count += 1 @@ -274,12 +292,13 @@ func Table_no_index_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("%d.【TABLE_SCHEMA: %s】【TABLE_NAME: %s】\n", count, Yellow(user.TABLE_SCHEMA), Green(user.TABLE_NAME)) } } else { - fmt.Println("———————————————————【没有无主键/索引的表】————————————————") + color.BgGreen.Println("———————————————————【没有无主键/索引的表】————————————————") } - fmt.Printf("—————————————————↑无主键/索引的表巡检完毕↑————————————————\n\n") + Completed.Printf("—————————————————↑无主键/索引的表巡检完毕↑————————————————") + fmt.Println(" \n ") } diff --git a/User/User_nopass_Inspection.go b/User/User_nopass_Inspection.go index c32c0d483709f56d5a99f6904390fe4d62f3422d..0058469303c177750e1deae683efe5282f77a4c0 100644 --- a/User/User_nopass_Inspection.go +++ b/User/User_nopass_Inspection.go @@ -1,22 +1,27 @@ package User import ( - "database/sql" + "DB_OSInspection/Global" "fmt" + + "github.com/gookit/color" ) type User struct { - TABLE_SCHEMA string - TABLE_NAME string - CHARACTER_SET_NAME string - Field_Type string - INDEX_COUNT int - SIZE_IN_GB float32 + TABLE_SCHEMA string + TABLE_NAME string } -func User_nopass_Inspection(db *sql.DB) { +var ( + // color + Green = color.Green.Render + Red = color.Red.Render + Completed = color.S256(255, 27) +) + +func User_nopass_Inspection() { sqlStr := "select user,host from mysql.user where authentication_string='';" - counts, err := db.Query(sqlStr) + counts, err := Global.DB.Query(sqlStr) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } @@ -30,7 +35,7 @@ func User_nopass_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【user: %s】【host: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("%d.【user: %s】【host: %s】\n", count, Green(user.TABLE_SCHEMA), Red(user.TABLE_NAME)) for counts.Next() { var user User count += 1 @@ -38,10 +43,11 @@ func User_nopass_Inspection(db *sql.DB) { if err != nil { panic(err.Error()) } - fmt.Printf("%d.【user: %s】【host: %s】\n", count, user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("%d.【user: %s】【host: %s】\n", count, Green(user.TABLE_SCHEMA), Red(user.TABLE_NAME)) } } else { - fmt.Println("————————————————————【没有无密码用户】——————————————————") + color.BgGreen.Println("————————————————————【没有无密码用户】——————————————————") } - fmt.Printf("———————————————————↑无密码用户巡检完毕↑—————————————————\n\n") + Completed.Printf("———————————————————↑无密码用户巡检完毕↑——————————————————") + fmt.Println(" \n ") } diff --git a/Variables/Variables_Inspection.go b/Variables/Variables_Inspection.go index 4d9ecf48b439bc518994a328bfd74b072eaa471b..3b5965a9d267e5d508f3ff1793c3d70a2d8a7509 100644 --- a/Variables/Variables_Inspection.go +++ b/Variables/Variables_Inspection.go @@ -1,20 +1,25 @@ package Variables import ( - "database/sql" + "DB_OSInspection/Global" "fmt" + + "github.com/gookit/color" ) type User struct { - TABLE_SCHEMA string - TABLE_NAME string - CHARACTER_SET_NAME string - Field_Type string - INDEX_COUNT int - SIZE_IN_GB float32 + TABLE_SCHEMA string + TABLE_NAME string } -func Variables_Inspection(db *sql.DB) { +var ( + // color + Green = color.Green.Render + Red = color.Red.Render + Completed = color.S256(255, 27) +) + +func Variables_Inspection() { var status_list = [...]string{"version", "innodb_buffer_pool_size", "innodb_flush_log_at_trx_commit", "innodb_log_file_size", "innodb_log_files_in_group", "innodb_file_per_table", "innodb_max_dirty_pages_pct", "sync_binlog", "max_connections", @@ -23,12 +28,13 @@ func Variables_Inspection(db *sql.DB) { var user User values := status_list[j] sqlStr := "show global variables like" + "'" + values + "'" - err := db.QueryRow(sqlStr).Scan(&user.TABLE_SCHEMA, &user.TABLE_NAME) + err := Global.DB.QueryRow(sqlStr).Scan(&user.TABLE_SCHEMA, &user.TABLE_NAME) if err != nil { fmt.Printf("scan failed, err:%v\n", err) } - fmt.Printf("【name: %s】【value: %s】\n", user.TABLE_SCHEMA, user.TABLE_NAME) + fmt.Printf("【name: %s】【value: %s】\n", Green(user.TABLE_SCHEMA), Red(user.TABLE_NAME)) } - fmt.Printf("——————————————————↑重要参数巡检完毕↑—————————————————————\n\n") + Completed.Printf("——————————————————↑重要参数巡检完毕↑—————————————————————") + fmt.Println(" \n ") } diff --git a/go.mod b/go.mod index 03a6bd32ffd1bed1437a32062c20098c2acf85ce..20a9acce48e721e556b9287a01c536f2de2f4624 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,12 @@ module DB_OSInspection go 1.20 -require github.com/go-sql-driver/mysql v1.7.0 +require ( + github.com/go-sql-driver/mysql v1.7.0 + github.com/gookit/color v1.5.3 +) + +require ( + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + golang.org/x/sys v0.6.0 // indirect +) diff --git a/go.sum b/go.sum index 7109e4cd0593451e138adddcac72fcb1078155e7..9d4ae08580848f06caed37adc9010f29da79301d 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,8 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= +github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index b526d0cb27f0ce20a424ab0e54ce2e4eb0610b08..cb7bfac9f97ce4aeb0d30814444952172ab9e677 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "DB_OSInspection/Global" "DB_OSInspection/Menu" "database/sql" "flag" @@ -64,7 +65,8 @@ func main() { nw := flag.String("nw", "tcp", "input netWork") //获取地址和端口号 P := flag.String("P", "localhost:3306", "input port") - //选择模式:all全部巡检、table只巡检表、index只巡检索引、variables只巡检重要参数、status只巡检重要状态、user只巡检用户、privileges只巡检权限 + /*选择模式:all全部巡检、table只巡检表、index只巡检索引、variables只巡检重要参数、 + status只巡检重要状态、user只巡检用户、privileges只巡检权限、monitor新增功能*/ m := flag.String("m", "all", "input model") //版本号 v := flag.Bool("v", false, "input port") @@ -77,8 +79,9 @@ func main() { return } - if *h { - flag.Usage() + if *h || *u == "" { + fmt.Println("Usage: DB OSInspection [options]") + flag.PrintDefaults() return } @@ -90,7 +93,7 @@ func main() { conn := fmt.Sprintf("%s:%s@%s(%s)/%s", *u, *p, *nw, *P, "mysql") db, err := sql.Open("mysql", conn) - + Global.DB = db if err != nil { getErrorMessage(err) } @@ -100,13 +103,12 @@ func main() { getErrorMessage(err) return } - //暂时不用设置此项 - // //设置最大连接数 - // db.SetMaxOpenConns(10) - // //最大空闲连接数 - // db.SetMaxIdleConns(10) - - Menu.Menu(db, *m) + //设置最大连接数 + db.SetMaxOpenConns(10) + //最大空闲连接数 + db.SetMaxIdleConns(10) + //跳转菜单页面 + Menu.Menu(*m) fmt.Println("感谢您使用数据库巡检工具 DB OSInspection")