對於不少服務來講,在同一個服務器上只能運行一個實例,那麼經過什麼方法來保證程序同一時刻只有一個實例運行呢?經過編寫shell腳原本管理程序的啓動、中止是個不錯的方法。在啓動時,shell腳本會建立進程標識文件(存儲正在運行實例的pid)以代表已經有實例在運行,若是文件已存在,則說明已有實例在運行,不須要作任何事;在退出時,shell腳本會刪除進程標識文件,代表沒有實例運行。shell
shell腳本管理方法在應用程序之上再包了一層,那麼能不能直接在程序開始運行時本身判斷是否有實例在運行呢,答案是確定的。原理其實差很少,仍是要藉助公用資源---文件,固然不單單是文件而已,還須要文件鎖的支持。大體思路是這樣的:程序在開始運行時對特定文件進行加鎖(不存在則建立),若是加鎖成功,則實例開始運行;如鎖已經被佔有,則說明已經有實例在運行,則程序直接退出;另外在實例運行完畢後對文件的鎖也隨着丟掉了。這樣就能保證每次只有一個程序實例在運行。服務器
具體步驟以下:code
1. 打開特定文件(如/var/run/mydaemon.pid),如不存在則建立之;
2. 使用fcntl對文件整個區域加勸告鎖;
3. 若是加鎖成功,則繼續執行後續代碼,並將pid寫入文件;如加鎖不成功,說明已經有實例在運行,直接退出。進程
t1.c資源
#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\n", filename); close(fd); return 1; } printf("can't lock %s: %m\n", filename); exit(1); } /* 寫入運行實例的pid */ ftruncate(fd, 0); sprintf(buf, "%ld\n", (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); }
結果:get
編譯運行string
查看pid文件中的進程號it
再次運行第二次io
失敗的, 只有第一個進程再運行。編譯