2

我有一个测试程序,我想从命令行运行该程序的多个副本,并且我需要知道要启动的程序的第一个实例。在 Dart 中,我按照有人向我建议的方式执行以下操作:

RawServerSocket.bind("127.0.0.1", 8087)

如果失败了,那么我知道另一个程序已经“锁定”了端口。这对我来说很好地解决了这个问题。当程序终止或显式关闭套接字时释放锁。

如何在 Go 中获得类似的结果?

4

3 回答 3

3

“unix 方式”是在 /var/run/<name>.pid 中创建一个 pid 文件 这就是我们使用 Docker 的方式https://github.com/dotcloud/docker/blob/master/docker/docker .go#L91 如果文件存在,则表示程序已经启动。

我不建议使用绑定方法,它会无缘无故地锁定一个端口,并且您不能确定其他程序没有使用该端口。

于 2013-09-24T17:26:19.423 回答
3

你没有说你正在使用哪个平台。如果您想跨平台,那么打开本地套接字的解决方案非常简单。这是您在 Go 中的操作方式。

package main

import (
    "log"
    "net"
    "time"
)

func main() {
    ln, err := net.Listen("tcp", "127.0.0.1:9876")
    if err != nil {
        log.Fatal("Failed to get lock: ", err)
    }
    defer ln.Close()
    log.Print("Started")
    time.Sleep(time.Second * 10)
    log.Print("Ending")
}

不幸的是,不使用套接字的跨平台方法非常困难,并且将涉及两组代码,一组用于类 Unix 系统,一组用于 Windows。

请注意,病毒检查程序不喜欢在 Windows 上打开侦听套接字的程序...

于 2013-09-24T21:54:12.863 回答
2

os.OpenFile()os.CREATE | os.O_EXCL标志一起使用怎么样?

file, err := os.OpenFile("lock", os.O_CREATE | os.O_EXCL | os.O_RDWR, 0400)
if err != nil {
        // Someone else has acquired the lock.
}
defer file.Close()
defer os.Remove("lock") // Ignoring errors here!

我没有编译或测试过这个,但它应该可以工作,无论如何,你明白了......

于 2013-09-24T20:57:01.550 回答