對于很多服務來說,在同一個服務器上只能運行一個實例沒有任務的實例在運行,那么通過什么方法來保證程序同一時刻只有一個實例運行呢?通過編寫shell腳本來管理程序的啟動、停止是個不錯的方法。在啟動時,shell腳本會創建進程標識文件(存儲正在運行實例的pid)以表明已經有實例在運行,如果文件已存在,則說明已有實例在運行,不需要做任何事;在退出時,shell腳本會刪除進程標識文件,表明沒有實例運行。
shell腳本管理方法在應用程序之上再包了一層,那么能不能直接在程序開始運行時自己判斷是否有實例在運行呢,答案是肯定的。原理其實差不多,還是要借助公用資源---文件沒有任務的實例在運行,當然不僅僅是文件而已,還需要文件鎖的支持。大致思路是這樣的:程序在開始運行時對特定文件進行加鎖(不存在則創建),如果加鎖成功,則實例開始運行;如鎖已經被占有,則說明已經有實例在運行,則程序直接退出;另外在實例運行完畢后對文件的鎖也隨著丟掉了。這樣就能保證每次只有一個程序實例在運行。
具體步驟如下:
1.打開特定文件(如/var/run/.pid),如不存在則創建之;
2.使用fcntl對文件整個區域加勸告鎖。
3.如果加鎖成功,則繼續執行后續代碼,并將pid寫入文件;如加鎖不成功,說明已經有實例在運行,直接退出。
實現示例:
#
#
#
#
#
#
#
#
#
# "/var/run/.pid"
# ( | | | )
/* set lock on file */
int (int fd)
{
flock fl;
fl. = ;/* write lock */
fl. = 0;
fl. = ;
fl.l_len = 0;//lock the whole file
(fcntl(fd, , &fl));
}
int (const char *)
{
int fd;
char buf[16];
fd = open(, | , );
if (fd < 0) {
("can't open %s: %m\n", );
exit(1);
}
/*先獲取文件鎖*/
if ((fd) == -1) {
if (errno == || errno == ) {
("file: %s ", );
close(fd);
1;
}
("can't lock %s: %m\n", );
exit(1);
}
/*寫入運行實例的pid */
(fd, 0);
(buf, "%ld", (long)());
write(fd, buf, (buf) + 1);
0;
}
int main(int argc, char *argv[])
{
if (())
0;
/*在這里添加工作代碼*/
("start main...\n");
sleep(100);
("main done!\n");
exit(0);
}
參考