zl程序教程

您现在的位置是:首页 >  工具

当前栏目

crond中使用flock命令的坑

命令 使用
2023-09-14 09:04:36 时间

需要定期去执行一个PHP脚本,首先想到的是通过crond命令来实现这个功能。但是,在crond的执行过程中发现一个诡异的事情。在crond中的配置如下。


*/1 * * * * root /usr/bin/flock -xn /tmp/test.lock -c /usr/bin/php /home/hailong/test.php /tmp/test.tt 2 1

脚本只会在第一次成功执行,之后就不会再执行。当删除/tmp/test.lock文件后,PHP脚本又能正常执行了。执行完一次后,就又不能正常执行了。



*/1 * * * * root /usr/bin/php /home/hailong/test.php /tmp/test.tt 2 1

发现脚本可以正常执行了。那必定是flock的问题。flock作为一个成熟的linux命令,有问题的可能性不大。最大的可能性就是PHP代码中某部分代码和flock冲突。PHP代码如下:


 ?php

$f = popen("/home/exfilter restart", "r");

while(!feof($f)) {

 $content = fgets($f, 1024);

 if (strpos($content, "start success") !== false) {

 break;

pclose($f);

file_put_contents("/tmp/test.log", date("Y-m-d H:i:s"));

? 

之前说过,只有第一次,flock的锁文件不存在的时候,才能正常执行。当锁文件存在后,就不再正常执行。PHP程序执行完毕后,flock并没有释文件锁。那我们看下,/tmp/test.lock文件是被那个文件所占用。


[hailong@vhost ~]$ sudo /usr/sbin/lsof | grep test.lock

exfilter 29821 root 3r REG 202,1 0 90439710 /tmp/test.lock

[hailong@vhost ~]$ ps aux | grep 29821

root 29821 0.1 0.2 175224 22596 ? Ssl 07:46 0:00 /home/exfilter -d

56667 30068 0.0 0.0 69460 852 pts/0 S+ 07:49 0:00 grep 29821

可见,test.lock文件正是被PHP程序中popen函数启动的进程所占用。由于,启动的是一个守护进程,进程不退出,锁一直被占用。


Linux系统上的文件锁主要分为协同锁(advisory lock)和强制锁(mandatory lock)。在Linux上使用的文件锁大部分为协同锁,而且使用强制锁的时候也要检查系统是否支持强制锁.
协同锁,是用户进程主动申请文件锁,锁才能起作用。比如,A进程已经对文件加了协同锁,如果B进程不去申请锁,而直接对文件进行写操作,也是可以的。
强制锁,是由操作系统内核保证的。不需要用户进程自己去申请。
flock命令使用的就是协同锁。
当一个主进程获取一个文件锁后,fork出的子进程也会获取这个文件锁。

12.11 Linux终止特定的一类进程(killall命令) killall 也是用于关闭进程的一个命令,但和 kill 不同的是,killall 命令不再依靠 PID 来杀死单个进程,而是通过程序的进程名来杀死一类进程,也正是由于这一点,该命令常与 ps、pstree 等命令配合使用。
linux命令之kill结束进程 kill 用于结束执行中的程序。 kill 可发送指定的信号到相应进程。不指定信号将发送SIGTERM(15)终止指定进程。若仍无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程,使用ps命令或者jobs 命令可以查看进程号。root用户将影响所有用户的进程,非root用户只能影响自己的进程。