我有一个测试程序,我想从命令行运行该程序的多个副本,并且我需要知道要启动的程序的第一个实例。在 Dart 中,我按照有人向我建议的方式执行以下操作:
RawServerSocket.bind("127.0.0.1", 8087)
如果失败了,那么我知道另一个程序已经“锁定”了端口。这对我来说很好地解决了这个问题。当程序终止或显式关闭套接字时释放锁。
如何在 Go 中获得类似的结果?
“unix 方式”是在 /var/run/<name>.pid 中创建一个 pid 文件 这就是我们使用 Docker 的方式https://github.com/dotcloud/docker/blob/master/docker/docker .go#L91 如果文件存在,则表示程序已经启动。
我不建议使用绑定方法,它会无缘无故地锁定一个端口,并且您不能确定其他程序没有使用该端口。
你没有说你正在使用哪个平台。如果您想跨平台,那么打开本地套接字的解决方案非常简单。这是您在 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 上打开侦听套接字的程序...
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!
我没有编译或测试过这个,但它应该可以工作,无论如何,你明白了......