要让一个程序单实例运行,可以采用PID文件的方法,demo程序如下:
oneinstance.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>std::string getExecutableName() {char buffer[1024];ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1);if (len != -1) {buffer[len] = '\0';std::string path(buffer);return path.substr(path.find_last_of("/") + 1); // 获取可执行文件名称}return "my_program"; // 默认名称
}bool isAlreadyRunning(const std::string &pidFilePath) {std::ifstream pidFile(pidFilePath);if (pidFile.is_open()) {pid_t pid;pidFile >> pid;if (pid > 0 && kill(pid, 0) == 0) { // 检查进程是否存在std::cout << "另一个实例已在运行,PID: " << pid << std::endl;return true;}}return false;
}void writePidFile(const std::string &pidFilePath) {std::ofstream pidFile(pidFilePath, std::ios::trunc);if (pidFile.is_open()) {pidFile << getpid();pidFile.close();} else {std::cerr << "无法创建 PID 文件: " << pidFilePath << std::endl;exit(EXIT_FAILURE);}
}int main() {std::string executableName = getExecutableName();std::string pidFilePath = "/tmp/" + executableName + ".pid";if (isAlreadyRunning(pidFilePath)) {return EXIT_FAILURE; // 如果已在运行,则退出}writePidFile(pidFilePath);std::cout << "程序正在运行,PID: " << getpid() << std::endl;// 模拟程序运行sleep(30); // 保持运行 30 秒// 删除 PID 文件remove(pidFilePath.c_str());return EXIT_SUCCESS;
}
编译:
g++ -static oneinstance.cpp -o oneinstance
运行:
lighthouse@VM-8-3-ubuntu:~/cplay/oneinstance$ ./oneinstance &
[1] 3396792
程序正在运行,PID: 3396792lighthouse@VM-8-3-ubuntu:~/cplay/oneinstance$ ./oneinstance
另一个实例已在运行,PID: 3396792
lighthouse@VM-8-3-ubuntu:~/cplay/oneinstance$ sleep 30
lighthouse@VM-8-3-ubuntu:~/cplay/oneinstance$ ./oneinstance
程序正在运行,PID: 3397293