【问题标题】:How to ping remote mysql using golang如何使用 golang ping 远程 mysql
【发布时间】:2016-12-09 05:43:37
【问题描述】:

我正在使用go ping 一些 Linux 机器。 但这并不准确,因为连接远程mysql总是需要将近10秒的时间。

我使用这个命令:

mysql -u 用户 -p 密码 -h 远程 IP

所以我想知道如何使用linux命令来知道它是否打开。

那我就用 golang 的 exec.Command 来做吧。

这是我的ping 代码:

package main

import (
    "errors"
    "fmt"
    "github.com/tatsushid/go-fastping"
    "net"
    "net/smtp"
    "strings"
    "time"
)

func main(){
    err := ping("192.168.2.1")
    if err != nil{
        fmt.Println("WARNING!!!!!!")
    }
}
func ping(ip string) error {
    p := fastping.NewPinger()
    ra, err := net.ResolveIPAddr("ip", ip)
    if err != nil {
        return err
    }
    p.AddIPAddr(ra)
    found := false
    p.OnRecv = func(addr *net.IPAddr, rtt time.Duration) {
        found = true
    }
    err = p.Run()
    if err != nil {
        return err
    }
    if !found {
        return errors.New("response error")
    }
    return nil
}

【问题讨论】:

    标签: mysql linux go


    【解决方案1】:

    我假设您想知道 mysql 是否可以访问。您可以使用以下示例:

    package main
    
    import (
        "database/sql"
        "flag"
        "fmt"
        "log"
    
        _ "github.com/go-sql-driver/mysql"
    )
    
    func main() {
        var (
            server = flag.String("mysql", "localhost:3306", "mysql server")
            user   = flag.String("user", "root", "mysql user")
            pass   = flag.String("password", "", "mysql password")
        )
        flag.Parse()
    
        db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", *user, *pass, *server))
        if err != nil {
            log.Fatalln(err)
    
        }
        defer db.Close()
    
        err = db.Ping()
    
        if err != nil {
            log.Fatalln(err)
    
        } else {
            log.Println("mysqld is alive")
    
        }
    
    }
    

    【讨论】:

    • 感谢您的帮助,但如果我想像 for {err = db.ping() iferr != nil {log.Fatalln(err)}} 一样整天使用 db.ping() 。但是,当我关闭某些机器时它不起作用。
    • log.Fatalln 替换为log.Println 并在ping 之间用time.Sleep 替换一些延迟。
    【解决方案2】:

    如果您只需要检查与特定主机和端口的连接,您可以这样做:

    package main
    
    import (
        "fmt"
        "net"
    )
    
    const (
        host = "192.168.2.1"
        port = "3306" // default MySQL port
    )
    
    func main() {
    
        conn, err := net.Dial("tcp", host+":"+port)
        if err != nil {
            panic(err)
        }
        defer conn.Close()
    
        fmt.Printf("Connected to %s \n", conn.RemoteAddr().String())
    }
    

    【讨论】:

    • 技术上有效但可能不合适,因为这种行为会导致 MySQL 假设连接主机有问题,并且如果 log_warnings 设置为高,则应导致记录警告。默认情况下,服务器将开始阻止您,如果您通过负载平衡器进行测试,这可能会特别糟糕:dev.mysql.com/doc/refman/5.7/en/blocked-host.html
    • haroldT 的问题有些模糊,无论如何,您无法确定与 MySQL 的连接状态,而实际上至少运行一个简单的查询,如“SELECT 1”。考虑到所有这些,并考虑到他的短语“... ping 一些 linux 机器...”,我认为他唯一关心的是特定主机上的端口是否打开。你对被阻止的主机有一个很好的观点!如果连接到端口 3306 的尝试会被 MySQL 视为“连接请求”,会很高兴吗? (下续)
    • (续) 在我的理解中,查看 MySQL 驱动程序,要“正式连接”,除了拨号之外,它还做了:身份验证,检查 max_allowed_pa​​cket,检查 charset + smth else。所以也许,只是 ping 端口不会导致主机'host_name'被阻止,因为实际上没有发生“连接请求”。想法?
    • 一次没有发送任何内容的 TCP 连接尝试,然后关闭连接,足以增加计数器。经测试确认:使用(旧)默认值 10,for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do (true | nc x.x.x.x 3306 | strings | egrep '^5|blocked'); done 会从第 12 次尝试开始导致Host 'xxxxxxx' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'(我不确定为什么不是第 10 次或第 11 次,但这种行为是可重复的)。
    • @Michael-sqlbot,太好了!感谢您检查。
    猜你喜欢
    • 1970-01-01
    • 2021-11-04
    • 2019-02-08
    • 2019-02-07
    • 2022-11-20
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多