crond中使用flock命令的坑 信海龙
2017-08-02 14:27
155 查看
crond中使用flock命令的坑
信海龙 linux crond
摘要: 现象 需要定期去执行一个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' 脚本只会在第一次成功执行,之后就不会再执行。
现象
需要定期去执行一个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脚本又能正常执行了。执行完一次后,就又不能正常执行了。
大家看到,配置文件最后增加了 2>&1。为啥要加2>&1呢?请查看博文《一个echo引起的进程崩溃》
另外,细心的朋友也会发现,我们使用了flock命令。使用flock命令是为了防止脚本被并发重复执行。更多控制crond脚本并发重复执行的方法,请查看《解决crond脚本执行并发冲突问题》
分析
把crond配置中把flock去掉。如下:*/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函数启动的进程所占用。由于,启动的是一个守护进程,进程不退出,锁一直被占用。
解决方法
启用flock命令,改用其他方法。更多方法请查看博文《解决crond脚本执行并发冲突问题》
延伸阅读
Linux系统上的文件锁主要分为协同锁(advisory lock)和强制锁(mandatory lock)。在Linux上使用的文件锁大部分为协同锁,而且使用强制锁的时候也要检查系统是否支持强制锁.协同锁,是用户进程主动申请文件锁,锁才能起作用。比如,A进程已经对文件加了协同锁,如果B进程不去申请锁,而直接对文件进行写操作,也是可以的。
强制锁,是由操作系统内核保证的。不需要用户进程自己去申请。
flock命令使用的就是协同锁。
当一个主进程获取一个文件锁后,fork出的子进程也会获取这个文件锁。
相关文章推荐
- linux中定时执行任务crond及crontab命令的使用
- Linux VPS 计划任务crond命令的使用方法分享
- Linux VPS 计划任务crond命令使用方法
- linux中定时任务crond命令使用方法
- 使用flock命令确保脚本单例执行
- linux 中flock命令的使用
- Linux任务调度进程crond命令的使用方法和注意事项
- 在Linux上使用flock命令控制程序的异步执行
- crond命令与find命令的使用
- sqlite3经常使用命令&语法
- CMD中使用attrib命令设置文件只读、隐藏属性详解
- 使用Adobe AIR 2的Native Process调用Curl命令
- Linux sudo命令配置与使用
- mysql使用source 命令乱码问题解决方法
- iptables 基本命令使用举例
- 在Android中使用adb命令时关于权限方面的一些总结
- Hillstone硬防使用手册+命令语句协议分析下载【3】
- git 基本命令使用总结
- 高效开发iOS系列(runtime篇) -- debug模式下使用po命令打印model的属性和值(runtime + debugDescription)
- 常用Shell命令及Vi的使用