监听日志写不进是因log_status未真正关闭,RAC需逐节点显式设置current_listener并验证;Windows下重命名后须reload释放句柄;清理应覆盖整个trace目录而非仅listener.log,且需避开ADR自动归档冲突。
监听日志写不进去了,先看 log_status 是不是真关了
很多 dba 执行 lsnrctl set log_status off 后就直接去 mv 或 ren 日志文件,结果发现新日志没生成、旧文件仍被占用——根本原因是 log_status 实际没关成功。rac 环境下每个节点有独立监听器,set current_listener 必须显式指定,否则命令只作用于默认监听器(通常是本地节点的 listener),其他节点日志仍在狂写。
验证方式:在每个节点分别执行:
lsnrctl LSNRCTL> set current_listener LISTENER_SCAN1 LSNRCTL> show log_status
确保返回 OFF;若为 ON,说明该节点监听日志仍在追加,此时移动文件会失败或导致后续写入异常。
-
show current_listener查当前上下文,避免误操作 - RAC 中常见监听名包括
LISTENER(本地)、LISTENER_SCAN1/2/3(SCAN)、LISTENER_NODE1等,不能假设统一 - 脚本中必须循环遍历所有监听名,不能只处理一个
Windows 下用 ren 重命名后,log_status on 不生成新 listener.log?
这是 Windows 平台特有陷阱:Oracle 监听器在 log_status on 时,并不会“创建”新文件,而是尝试打开已配置的 log_file 路径对应文件。如果该路径下已有同名文件(哪怕刚被 ren 过),监听器会继续往里面追加;如果路径下无文件,它才新建。但问题在于:ren listener.log listener.log.20260515 后,原文件句柄仍被 tnslsnr.exe 持有,Windows 不允许立即覆盖或重建同名文件。
正确做法是关日志 → 重命名 → 再执行一次 lsnrctl reload(非 start)→ 再开日志:
-
reload强制监听器重新读取listener.ora,释放旧句柄并按配置路径打开新文件 - 仅靠
set log_status on不触发文件句柄刷新,新日志仍可能写入旧文件(即使已被重命名) - Windows 下不要用
cls > listener.log清空,这会锁定文件导致后续log_status on失败
RAC 环境清理脚本必须避开 ADR 自动归档冲突
Oracle 11g RAC 默认启用 ADR(DIAGNOSTIC_DEST),而 ADR 自带的 adrci 工具也会定期扫描 trace 目录做归档和压缩。如果你的定时脚本在凌晨 2 点运行,而 ADR 的自动 purge 也在同一时段触发(默认保留 7 天),两个进程同时操作 listener.log 和同目录下的其他 .trc 文件,极易引发文件句柄竞争、lsnrctl status 卡死、甚至监听器假死。
规避方法:
- 查 ADR 当前策略:
adrci -script中执行show control,确认SHORTP_POLICY和LONGP_POLICY值 - 将自定义清理脚本时间错开 ADR 默认周期(如设为每天 03:17,而非整点)
- 脚本开头加锁检测:
if exist listener.log.lock exit /b,避免并发执行 - 禁用 ADR 对监听日志的自动管理(不推荐),改用
ALTER SYSTEM SET DIAGNOSTIC_DEST=''会破坏整个诊断体系,得不偿失
为什么清完日志,lsnrctl status 还是慢?
这不是日志文件本身的问题,而是 trace 目录下堆积了成千上万个 .trc、.log、.xml 文件。Windows NTFS 在单目录超 5000 文件时,lsnrctl 执行 status 需遍历整个目录获取最新时间戳和状态,I/O 延迟飙升。你删了 listener.log,但没动那些 ora_12345.trc,问题照旧。
真正要清理的是整个 trace 目录的“历史陈迹”,不是只盯着 listener.log:
- 用
adrci安全清理:adrci exec "purge -age 1440 -type TRACE"(清除 24 小时前 trace) - Linux 脚本可用
find $ADR_HOME/trace -name "*.trc" -mtime +1 -delete,但 Windows 没mtime,得用forfiles+date计算 - 切勿手动删
log.xml或alert子目录——那是数据库实例自己的告警日志,删错会导致实例无法启动
最常被忽略的一点:RAC 中每个节点的 trace 目录必须单独清理,脚本里漏掉任意一个节点,那个节点的监听就会持续卡顿。











