直接rm -rf listener.log会导致tnslsnr进程继续向已删除inode写日志,磁盘空间不释放,且老版本系统可能因write()失败引发连接拒绝;正确做法是先lsnrctl set log_status off,再截断文件,最后set log_status on。
为什么直接 rm -rf listener.log 会出问题
rac 环境下监听日志 listener.log 膨胀后,很多人习惯用 rm -f $oracle_home/network/log/listener.log 直接删。但这个操作会导致 tnslsnr 进程继续往已删除的 inode 写日志,磁盘空间不释放,df -h 看不到回收,且日志实际还在 /proc/<pid>/fd/</pid> 下挂着。更糟的是,某些老版本(如 aix 或 32 位 linux)遇到 >2gb 的 listener.log 可能触发连接拒绝——不是因为“超 2g 就挂”,而是文件系统或 libc 的 write() 失败未被监听器正确处理。
必须用 lsnrctl set log_status off + 截断,不能删文件
正确做法是让监听器主动停止写入,再清空内容。顺序错一步就白干:
- 先执行
lsnrctl set log_status off(注意:必须在监听器运行状态下执行,否则报LSNRCTL> set: command not found) - 再用
cp /dev/null $ORACLE_HOME/network/log/listener.log或echo -n > $ORACLE_HOME/network/log/listener.log—— 不要用rm后touch,那会换 inode - 最后
lsnrctl set log_status on恢复记录 - 验证:
ls -l $ORACLE_HOME/network/log/listener.log应显示大小为 0,且tail -f能看到新日志实时追加
crontab 自动清理脚本要带节点标识和锁保护
RAC 多节点共用同一套 $ORACLE_HOME,但每个节点的监听器独立运行。若所有节点都跑同一个 crontab 脚本,可能并发执行导致 log_status 切换冲突或截断失败。
- 脚本开头加判断:
if [ "$(hostname)" != "rac1" ]; then exit 0; fi(按需替换成本节点名) - 加文件锁避免重复执行:
if ! ln -s "$0" "$0.lock" 2>/dev/null; then exit 0; fi; trap 'rm -f "$0.lock"' EXIT - 日志归档命名必须含节点名:
cp $OH/network/log/listener.log $OH/network/log/listener.log.$(hostname).$(date +%Y%m%d) - 保留归档最多 30 天:
find $OH/network/log -name "listener.log.*" -mtime +30 -delete
alert_sid.log 和 trace 日志别混着清
alert_<code>sid.log 和后台进程 trace 文件(如 ora_<pid>_<code>sid.trc)不属于“集群日志”,但常被误一起清理。它们路径分散:
-
alert_<code>sid.log 在$ORACLE_BASE/diag/rdbms/<db_name>/<code>sid/trace/ - trace 文件在
$ORACLE_BASE/diag/rdbms/<db_name>/<code>sid/trace/ 或$ORACLE_HOME/rdbms/log/(旧版) - 用
adrci更安全:adrci exec "set homepath diag/rdbms/orcl/orcl1; purge -age 4320"(单位分钟,即 3 天) - 切忌对
trace/目录直接rm -f *.trc—— 可能删掉正在写的当前 trace,引发 ORA-00600
log_status off 或跨节点没隔离,轻则日志丢失,重则监听器静默失效。











