在 Linux 中,可以通过文件锁来实现进程单例。具体实现步骤如下:
在程序运行时,尝试以只读方式打开一个特定的文件(例如 /var/run/myprocess.pid)。
如果文件不存在,则创建该文件,并将当前进程 ID 写入该文件中。
如果文件已经存在,则读取其中的进程 ID,并检查该进程是否仍在运行。如果该进程还在运行,则退出当前进程;否则,覆盖该文件中的进程 ID 为当前进程 ID。
代码示例:
package main
import (
"fmt"
"os"
"strconv"
"syscall"
)
func processSingleton() bool {
pidFile := "/var/run/myprocess.pid"
// 尝试获取文件锁
file, err := os.OpenFile(pidFile, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return false
}
defer file.Close()
if syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB) != nil {
return false
}
// 锁定成功,写入当前进程 ID
pid := strconv.Itoa(os.Getpid())
_, err = file.WriteString(pid)
if err != nil {
fmt.Println("write pid to file error:", err)
return false
}
return true
}
func main() {
if !processSingleton() {
fmt.Println("process already running")
os.Exit(1)
}
fmt.Println("start process...")
// 后续操作...
}
以上代码中,我们首先尝试以可读可写方式打开指定的文件,并使用 syscall.Flock 函数获取共享锁。如果获取失败,则说明其他进程已经占用了该资源,当前进程无法再启动,直接返回失败。如果获取成功,则将当前进程 ID 写入文件中,并返回成功。
需要注意的是,在程序退出时应该显式地释放文件锁和关闭文件句柄,以避免资源泄漏。




