原文地址:http://blog.chinaunix.net/uid-24622573-id-276141.html
對於很多服務來說,在同一個伺服器上只能運行一個執行個體,那麼通過什麼方法來保證程式同一時刻只有一個執行個體運行呢?通過編寫shell指令碼來管理程式的啟動、停止是個不錯的方法。在啟動時,shell指令碼會建立進程標識檔案(儲存正在運行執行個體的pid)以表明已經有執行個體在運行,如果檔案已存在,則說明已有執行個體在運行,不需要做任何事;在退出時,shell指令碼會刪除進程標識檔案,表明沒有執行個體運行。
shell指令碼管理方法在應用程式之上再包了一層,那麼能不能直接在程式開始運行時自己判斷是否有執行個體在運行呢,答案是肯定的。原理其實差不多,還是要藉助公用資源---檔案,當然不僅僅是檔案而已,還需要檔案鎖的支援。大致思路是這樣的:程式在開始運行時對特定檔案進行加鎖(不存在則建立),如果加鎖成功,則執行個體開始運行;如鎖已經被佔有,則說明已經有執行個體在運行,則程式直接退出;另外在執行個體運行完畢後對檔案的鎖也隨著丟掉了。這樣就能保證每次只有一個程式執行個體在運行。
具體步驟如下:
1. 開啟特定檔案(如/var/run/mydaemon.pid),如不存在則建立之;
2. 使用fcntl對檔案整個地區加勸告鎖。
3. 如果加鎖成功,則繼續執行後續代碼,並將pid寫入檔案;如加鎖不成功,說明已經有執行個體在運行,直接退出。
實現樣本:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <printf.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#define LOCKFILE "/var/run/mydaemon.pid"
#define LOCKMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/* set advisory lock on file */
int lockfile(int fd)
{
struct flock fl;
fl.l_type = F_WRLCK; /* write lock */
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0; //lock the whole file
return(fcntl(fd, F_SETLK, &fl));
}
int already_running(const char *filename)
{
int fd;
char buf[16];
fd = open(filename, O_RDWR | O_CREAT, LOCKMODE);
if (fd < 0) {
printf("can't open %s: %m\n", filename);
exit(1);
}
/* 先擷取檔案鎖 */
if (lockfile(fd) == -1) {
if (errno == EACCES || errno == EAGAIN) {
printf("file: %s already locked", filename);
close(fd);
return 1;
}
printf("can't lock %s: %m\n", filename);
exit(1);
}
/* 寫入運行執行個體的pid */
ftruncate(fd, 0);
sprintf(buf, "%ld", (long)getpid());
write(fd, buf, strlen(buf) + 1);
return 0;
}
int main(int argc, char *argv[])
{
if (already_running(LOCKFILE))
return 0;
/* 在這裡添加工作代碼 */
printf("start main...\n");
sleep(100);
printf("main done!\n");
exit(0);
}