我有一个测试程序,我想从命令行运行程序的多个副本,我需要知道要启动的程序的第一个实例。在达特,我做了以下有人向我建议的事情:
RawServerSocket.bind("127.0.0.1", 8087)
如果失败,那么我知道另一个程序已“锁定”该端口。这对我来说足以解决问题。程序终止或明确关闭套接字时释放锁。
如何在Go中获得类似的结果?
答案 0 :(得分:3)
'unix方式'是在/var/run/<name>.pid中创建一个pid文件 我们就是这样做的Docker https://github.com/dotcloud/docker/blob/master/docker/docker.go#L91 如果该文件存在,则表示该程序已经启动。
我不建议使用bind方法,它只是没有锁定端口,你不能确定其他程序没有使用该端口。
答案 1 :(得分: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上打开侦听套接字的程序...
答案 2 :(得分: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!
我没有编译或测试过这个,但是它应该可以工作,无论如何,你明白了......