我有一个用 PHP 编写的长期运行的 CLI cron 作业。在一段不一致的时间段后,脚本停止将输出写入其日志文件,表明它已停止执行。
然而,脚本仍然在运行,已确认ps aux
。
脚本没有抛出任何异常或输出任何错误。当它停滞时,它似乎不会再消耗任何 CPU。
内存不是问题 - 脚本使用内存ini_set("memory_limit", "1G");
,当脚本仅使用约 73 MB 时似乎会冻结。脚本在功能强大的专用机器(8 GB RAM、8 个 CPU、PHP 5.6.25)上运行,具有充足的可用内存、磁盘空间、inode、/tmp 空间、可用 CPU 等。
使用 xdebug 的函数跟踪日志记录,我可以看到脚本只是在一个不起眼的函数调用处停止。xdebug 的“正常”执行会TRACE END [2019-03-26 13:02:55]
在日志文件末尾写入类似这样的内容,然后退出。但是,当脚本冻结时,不会出现此行,并且脚本不会退出。例如:
“停滞”的 xdebug 功能日志,示例 A:
1481.7659 73187512 -> in_array() /home/xyz/inc/util/email.inc:156
1481.7659 73187056 -> strpos() /home/xyz/inc/util/email.inc:170
1481.7659 73187208 -> mail() /home/xyz/inc/util/email.inc:181
“失速”并不总是发生在同一事件上。
“停滞”的 xdebug 功能日志,示例 B:
1422.5710 73306784 -> strrpos() /home/xyz/inc/util/external-common.inc:106
1422.5710 73306840 -> substr() /home/xyz/inc/util/external-common.inc:108
1422.5710 73307008 -> shell_exec() /home/xyz/inc/util/external-common.inc:112
“正常”的 xdebug 功能日志:
55190.4859 35183552 -> WP_Object_Cache->__destruct() /home/xyz/public_html/wp/wp-includes/cache.php:0
55190.8278 34830224 -> wpdb->__destruct() /home/xyz/public_html/wp/wp-includes/wp-db.php:0
55193.1823 8672
TRACE END [2019-03-26 13:02:55]
这可能只是巧合,但我能看到的唯一共同点是可能与 C 有关popen()
- 它(或相关)似乎被 PHP 所使用mail()
和shell_exec()
。我认为我没有打开太多进程(最近验证过;手头没有我使用的命令)。该脚本shell_exec()
每秒最多只执行 5 次调用,每次调用执行时间不到一秒钟。(另外,如果这是一个问题,我会不会收到某种错误而不是这种“停滞”行为?)
会发生什么事?
我下一步该怎么做?
答案1
进一步跟踪,直到任何用户或内核级别的函数花费很长时间。
用于ltrace
观察系统调用和 C 库调用。了解它正在做什么。
为了追踪执行程序的理论,尝试观察高管execsnoop
。
在同一个脚本集合中,检查始终使用 DNS 的流行 meme gethostlatency
。
这两个都是 eBPF,因此在 CentOS 内核中不可用。但是,您可能会在可用工具(如 ftrace)中找到或编写它们的变体。