如何过滤WordPress站点debug.log,仅查看自定义代码错误
解决方案:分离WordPress第三方插件与自定义代码的错误日志
需求明确:将/wp-content/plugins/admin-columns-pro/、/wp-content/plugins/yoast/路径产生的错误写入wp-content/vendor-debug.log,自定义插件(my-plugin-foo、my-plugin-bar)和主题(my-custom-theme)的错误保留在原debug.log。以下是几个可行的落地方案:
方案1:利用WordPress内置过滤器wp_error_log(推荐)
直接借助WordPress原生钩子拦截日志,无需修改核心代码,风险极低。将以下代码放入主题functions.php或自定义插件的主文件中:
add_filter('wp_error_log', function($message, $level) { // 定义需要分流的第三方插件路径标识 $vendor_paths = [ '/wp-content/plugins/admin-columns-pro/', '/wp-content/plugins/yoast/' ]; // 检查日志内容是否包含第三方插件路径 $is_vendor_error = false; foreach ($vendor_paths as $path) { if (strpos($message, $path) !== false) { $is_vendor_error = true; break; } } if ($is_vendor_error) { // 写入第三方专用日志文件 $vendor_log = WP_CONTENT_DIR . '/vendor-debug.log'; error_log($message . PHP_EOL, 3, $vendor_log); // 返回空字符串,阻止写入原debug.log return ''; } // 非第三方错误,保留原写入逻辑 return $message; }, 10, 2);
注意:确保wp-content目录具备服务器写入权限,否则日志文件无法生成。
方案2:实时自动过滤的Bash脚本
针对原手动脚本的痛点,用inotifywait监控日志文件变化,实现实时分流。
步骤1:安装依赖(Debian/Ubuntu)
sudo apt-get install inotify-tools
步骤2:创建脚本log-splitter.sh
#!/bin/bash # 替换为你的实际路径 DEBUG_LOG="/var/www/debug.log" VENDOR_LOG="/var/www/wp-content/vendor-debug.log" # 需要过滤的第三方插件目录名 VENDOR_PATHS=("admin-columns-pro" "yoast") # 初始化日志文件 touch $DEBUG_LOG $VENDOR_LOG # 实时监控debug.log新增内容 tail -n0 -f $DEBUG_LOG | while read line; do is_vendor=0 for path in "${VENDOR_PATHS[@]}"; do if echo "$line" | grep -q "/wp-content/plugins/$path/"; then is_vendor=1 break fi done if [ $is_vendor -eq 1 ]; then echo "$line" >> $VENDOR_LOG # 可选:如果需要从原debug.log删除第三方日志,取消下面注释 # sed -i "\|$line|d" $DEBUG_LOG fi done
步骤3:设置脚本自启
给脚本添加执行权限:
chmod +x log-splitter.sh
后台运行并开机自启(用nohup):
nohup ./log-splitter.sh &
方案3:PHP自定义错误处理器(底层控制)
如果需要完全接管错误日志流程,可自定义PHP错误处理器,直接拦截所有错误并判断来源:
function custom_error_handler($errno, $errstr, $errfile, $errline) { // 定义第三方插件路径前缀 $vendor_prefixes = [ WP_CONTENT_DIR . '/plugins/admin-columns-pro/', WP_CONTENT_DIR . '/plugins/yoast/' ]; $is_vendor_error = false; foreach ($vendor_prefixes as $prefix) { if (strpos($errfile, $prefix) === 0) { $is_vendor_error = true; break; } } // 选择目标日志文件 $log_file = $is_vendor_error ? WP_CONTENT_DIR . '/vendor-debug.log' : WP_CONTENT_DIR . '/../debug.log'; // 格式化错误消息,匹配WordPress默认日志格式 $message = sprintf( '[%s] PHP %s: %s in %s on line %d', date('d-M-Y H:i:s T'), error_type_to_string($errno), $errstr, $errfile, $errline ); error_log($message . PHP_EOL, 3, $log_file); // 致命错误需正常终止程序 if (in_array($errno, [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { exit(1); } return true; } // 注册错误处理器 set_error_handler('custom_error_handler'); // 补充处理致命错误(set_error_handler无法捕获) register_shutdown_function(function() { $error = error_get_last(); if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { custom_error_handler($error['type'], $error['message'], $error['file'], $error['line']); } }); // 辅助函数:将错误码转为对应字符串 function error_type_to_string($errno) { switch ($errno) { case E_ERROR: return 'Error'; case E_WARNING: return 'Warning'; case E_PARSE: return 'Parse error'; case E_NOTICE: return 'Notice'; case E_DEPRECATED: return 'Deprecated'; case E_USER_ERROR: return 'User Error'; case E_USER_WARNING: return 'User Warning'; case E_USER_NOTICE: return 'User Notice'; case E_USER_DEPRECATED: return 'User Deprecated'; default: return 'Unknown error type'; } }
说明:该方案直接从PHP层面拦截错误,兼容性需注意与WordPress原生错误处理逻辑的适配,适合需要深度定制的场景。
内容的提问来源于stack exchange,提问作者Zeth
相关产品推荐
相关产品推荐

