我来填之前开的坑了,EMLOG友链状态实时更新工具已经写好了。接下来看看功能以及如何使用吧(*^▽^*)
简介
EMLOG友链状态实时更新插件是一款用于检测和显示友情链接状态的插件。通过该插件,您可以实时监测友情链接是否正常,方便及时处理异常链接,确保友情链接的稳定性和有效性。
功能特点
- 实时监测友情链接状态
- 目前仅支持状态码监测,后续将更新其他监测方式
大概 - 异常状态提醒功能
嗯~待实现~~
安装方法
- Linux用户可以点我下载
- 下载后将压缩包解压,按照配置文件conf.yaml进行配置
- 给予执行权限:
chmod +x emstatus && nohup emstatus > /dev/null 2>&1 &
注:其他平台可以自行复制下面代码进行二进制构建
配置项说明
- time: 10s 监测时间间隔,每隔多久对友链检测一次,支持时【h】分【m】秒【s】组合
- action: 0 如果检测到无法访问如何处理0【隐藏友链】1【删除友链】,建议隐藏
工具源码
<code">package main import ( "crypto/tls" "database/sql" "fmt" "io" "log" "os" "sync" "time" _ "github.com/go-sql-driver/mysql" "gopkg.in/resty.v1" "gopkg.in/yaml.v2" ) type Config struct { MySQL struct { Host string `yaml:"host"` Port int `yaml:"port"` User string `yaml:"user"` Password string `yaml:"password"` Database string `yaml:"database"` } `yaml:"mysql"` Links struct { Time string `yaml:"time"` Action int `yaml:"action"` } `yaml:"links"` } func main() { client := resty.New(). SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) config, err := readConfig("conf.yaml") if err != nil { log.Fatalf("无法读取配置文件: %v", err) } interval, err := time.ParseDuration(config.Links.Time) if err != nil { log.Fatalf("无法解析时间间隔: %v", err) } dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", config.MySQL.User, config.MySQL.Password, config.MySQL.Host, config.MySQL.Port, config.MySQL.Database, ) db, err := sql.Open("mysql", dsn) if err != nil { log.Fatal(err) } defer db.Close() err = db.Ping() if err != nil { log.Fatal(err) } fmt.Println("成功连接到数据库!") for { checkLinks(db, client, config) time.Sleep(interval) } } func checkLinks(db *sql.DB, client *resty.Client, config *Config) { rows, err := db.Query("SELECT id, siteurl FROM emlog_link WHERE hide = 'n'") if err != nil { log.Fatal(err) } defer rows.Close() var wg sync.WaitGroup columns, err := rows.Columns() if err != nil { log.Fatal(err) } values := make([]interface{}, len(columns)) valuePtrs := make([]interface{}, len(columns)) for i := range values { valuePtrs[i] = &values[i] } log.Printf("================================================================") for rows.Next() { err := rows.Scan(valuePtrs...) if err != nil { log.Fatal(err) } result := make(map[string]interface{}) for i, col := range columns { val := values[i] if b, ok := val.([]byte); ok { result[col] = string(b) } else { result[col] = val } } wg.Add(1) go func(result map[string]interface{}) { defer wg.Done() log.Printf("正在检测友链: %s", result["siteurl"].(string)) res, err := client.R().Get(result["siteurl"].(string)) if err != nil { if config.Links.Action == 0 { log.Printf("友链检测失败,将对友链进行【隐藏】,错误信息: %s", err) } else if config.Links.Action == 1 { log.Printf("友链检测失败,将对友链进行【删除】,错误信息: %s", err) } } if res.StatusCode() != 200 && config.Links.Action == 0 { _, err := db.Exec("UPDATE emlog_link SET hide = 'y' WHERE id = ?", result["id"]) if err != nil { log.Printf("更新记录失败: %v", err) } } else if res.StatusCode() != 200 && config.Links.Action == 1 { _, err := db.Exec("DELETE FROM emlog_link WHERE id = ?", result["id"]) if err != nil { log.Printf("删除记录失败: %v", err) } } }(result) } if err = rows.Err(); err != nil { log.Fatal(err) } wg.Wait() } func readConfig(path string) (*Config, error) { var config Config file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() data, err := io.ReadAll(file) if err != nil { return nil, err } err = yaml.Unmarshal(data, &config) if err != nil { return nil, err } return &config, nil }