别再用rm删日志了Oracle19c的adrci隐藏功能全解析含定时清理脚本深夜两点手机突然响起刺耳的告警铃声——“磁盘使用率超过95%”。你睡眼惺忪地爬起来连上服务器发现又是Oracle的日志目录在“作祟”。/u01/app/oracle/diag下trace、incident、alert文件堆积如山listener.log早已膨胀到几个GB。你熟练地敲下rm -rf心里却清楚这只是饮鸩止渴。删错了怎么办哪些能删哪些不能删下次告警又是什么时候这种被动的、充满风险的“救火”模式是不是该彻底终结了如果你对上述场景感同身受那么这篇文章就是为你准备的。我们不再讨论那些基础的、零散的adrci命令而是深入挖掘Oracle 19c中这个被严重低估的自动化诊断仓库命令行工具的“隐藏”能力。adrci远不止是一个查看日志的工具它是一个内置的、智能的、安全的日志生命周期管理器。今天我们将彻底告别手动rm的蛮荒时代系统性地掌握如何利用adrci的purge命令及其精妙的参数组合构建一套无人值守的、策略化的日志清理体系并最终通过crontab实现自动化让你从此高枕无忧。1. 为什么说rm -rf是DBA的“危险游戏”在深入adrci之前我们必须先达成一个共识直接使用操作系统命令如rm、find删除Oracle诊断文件是一项高风险操作。这并非危言耸听而是无数血泪教训的总结。首先是精准定位的难题。Oracle的自动诊断仓库ADR结构复杂不同组件如数据库实例、ASM、监听器的日志分布在不同的HOME下。例如数据库alert log:$ORACLE_BASE/diag/rdbms/db_name/instance_name/trace/alert_instance_name.log监听器日志$ORACLE_BASE/diag/tnslsnr/hostname/listener/alert/log.xml集群日志GI$GRID_HOME/log/hostname/...手动定位这些路径不仅繁琐而且在多实例、多组件的环境中极易出错。你可能会误删仍在被进程写入的关键跟踪文件导致实例挂起或产生不可预知的错误。其次是依赖关系的破坏。ADR中的文件并非孤立存在。一个incident意外事件可能关联多个trace文件、dmp文件以及alert log中的条目。adrci的purge命令在设计时充分考虑了这种关联性它会智能地清理一个事件相关的所有诊断数据。而粗暴的rm命令会留下“孤儿”文件使得后续的问题诊断变得支离破碎无法还原完整的故障现场。再者是安全性的缺失。adrci purge是一个事务性的、受Oracle数据库管理的操作。它在执行前会进行内部检查确保不会删除正在被活动进程使用的文件。而rm命令则毫无顾忌一旦误删核心文件恢复将极其困难。注意我曾亲眼见过一个开发同事在清理空间时误将整个diag/rdbms目录删除导致所有数据库实例的日志和诊断信息丢失。当生产环境突发性能问题时由于缺乏关键时间段的trace文件问题排查陷入了僵局教训惨痛。最后手动清理无法形成可持续的策略。依赖人工记忆或临时脚本清理周期不固定阈值不明确最终总会陷入“磁盘告警-手动清理-再次告警”的恶性循环。而adrci的核心价值就在于它将“清理”这个动作从临时操作提升到了策略管理的层面。2. 深入核心adrci purge命令的参数化艺术adrci的purge命令之所以强大在于其高度参数化的设计。它不像rm那样“一删了之”而是允许你基于时间和类型两个维度进行外科手术式般的精准清理。理解这两个维度的组合是玩转adrci的关键。2.1 时间维度-age参数的“时间胶囊”-age参数的单位是分钟。这是最容易让人混淆的地方。我们习惯用“天”来思考但adrci要求我们输入分钟数。这就需要一点简单的计算。为了方便大家这里有一个常用时间转换的速查表描述天数分钟数 (age参数值)适用场景举例最近1小时-60清理非常临时的调试trace最近1天11440清理昨日测试产生的临时文件最近1周710080常规的trace文件滚动清理最近30天3043200最常用的警报日志清理周期最近90天90129600保留季度级别的诊断信息最近180天180259200合规或审计要求的长期保留最近1年365525600监听日志等低价值大文件的超长期清理核心技巧-age 4320030天是一个黄金标准。对于大多数生产环境的alert log和trace文件保留一个月通常足以覆盖一次完整的迭代周期和问题回溯。更早的文件其诊断价值急剧下降但空间占用却是实实在在的。2.2 类型维度-type参数的“靶向清除”-type参数让你指定要清理的诊断数据类型避免误伤。Oracle ADR将诊断数据分门别类主要类型如下ALERT警报日志文件。这是最常见的清理对象包括数据库的alert_SID.log和监听器的log.xml。INCIDENT意外事件包。当数据库发生严重错误如ORA-600时会自动创建一个incident包含相关的dump和trace文件。这些文件通常较大且一旦问题解决历史incident就可以清理。TRACE后台进程和用户会话的跟踪文件。这是空间占用的“大户”尤其是开启了SQL跟踪或遇到大量错误时。CDUMP核心转储文件。当Oracle进程异常终止时产生文件通常非常大除非正在调试核心问题否则可以安全清理。HM健康监视器运行报告。占用空间较小一般无需特别清理。UTSCDMP用户跟踪状态转储。相对少见。组合使用的威力-age和-type的组合让你可以制定极其精细的策略。例如purge -age 10080 -type trace清理一周前的所有跟踪文件释放大量空间同时保留近期可能用于诊断的文件。purge -age 43200 -type alert清理30天前的警报日志这是保持alert log可读性的标准操作。purge -age 129600 -type incident清理90天前的历史意外事件包这些通常已失去调查意义。purge -age 525600 -type alert清理一年前的监听器日志(log.xml)这种日志增长快且价值衰减慢可以设置更长的周期。2.3 实战演练从登录到执行的完整流程理论说再多不如动手试一次。我们以一个单机Oracle 19c环境为例走一遍完整的流程。首先切换到oracle用户并启动adrcisu - oracle adrci进入adrci交互界面后第一件事是查看当前可用的ADR主目录ADR Homes。这在RAC环境或单机多库环境下尤为重要。adrci show home ADR Homes: diag/rdbms/prodcdb/PRODCDB diag/tnslsnr/linux01/listener输出显示有两个HOME数据库实例PRODCDB和监听器。我们需要针对不同的HOME执行清理。使用set homepath命令切换上下文# 切换到数据库实例HOME adrci set homepath diag/rdbms/prodcdb/PRODCDB # 执行清理删除30天前的跟踪文件和警报日志 adrci purge -age 43200 -type trace adrci purge -age 43200 -type alert # 切换到监听器HOME adrci set homepath diag/tnslsnr/linux01/listener # 删除90天前的监听器警报日志 adrci purge -age 129600 -type alert执行后adrci会输出被删除的文件列表和释放的空间总量让你对清理效果一目了然。提示在执行大规模清理前特别是首次在某个环境使用强烈建议先使用show incident、show tracefile等命令查看现有文件情况或者先用一个较大的-age值如-age 525600试运行确认无误后再应用真实的策略。3. 超越交互编写可重用的Shell脚本每次都手动登录adrci并输入命令显然不符合我们自动化的目标。我们需要将上述过程脚本化。一个健壮的脚本应该考虑以下几点错误处理、日志记录、多HOME环境适配。下面是我在多个生产环境中使用的增强版清理脚本purge_adr.sh#!/bin/bash # Author: DBA Expert # Description: Purge old Oracle ADR files for all ADR homes # Usage: ./purge_adr.sh set -o nounset set -o errexit # 配置变量 LOG_FILE/var/log/oracle/adr_purge.log RETENTION_DAYS_TRACE7 # 保留7天trace RETENTION_DAYS_ALERT30 # 保留30天alert log RETENTION_DAYS_INCIDENT90 # 保留90天incident RETENTION_DAYS_LISTENER_ALERT180 # 保留180天监听日志 # 转换天数为分钟数 AGE_TRACE$((RETENTION_DAYS_TRACE * 1440)) AGE_ALERT$((RETENTION_DAYS_ALERT * 1440)) AGE_INCIDENT$((RETENTION_DAYS_INCIDENT * 1440)) AGE_LISTENER_ALERT$((RETENTION_DAYS_LISTENER_ALERT * 1440)) # 日志函数 log_message() { echo [$(date %Y-%m-%d %H:%M:%S)] $1 | tee -a $LOG_FILE } # 主函数 main() { log_message Starting ADR Purge Cycle # 检查adrci是否可用 if ! command -v adrci /dev/null; then log_message ERROR: adrci command not found. Check ORACLE_HOME. exit 1 fi # 获取所有ADR Home log_message Getting ADR Homes... ADR_HOMES$(echo show home | adrci | grep diag/ | tr -d ) if [ -z $ADR_HOMES ]; then log_message No ADR Homes found. Exiting. exit 0 fi # 遍历每个HOME并执行清理 while IFS read -r ADR_HOME; do log_message Processing ADR Home: $ADR_HOME # 根据HOME类型应用不同的策略 if [[ $ADR_HOME *diag/rdbms* ]]; then # 数据库实例HOME log_message Purging TRACE files older than $RETENTION_DAYS_TRACE days... echo set homepath $ADR_HOME; purge -age $AGE_TRACE -type trace; | adrci $LOG_FILE 21 log_message Purging ALERT files older than $RETENTION_DAYS_ALERT days... echo set homepath $ADR_HOME; purge -age $AGE_ALERT -type alert; | adrci $LOG_FILE 21 log_message Purging INCIDENT files older than $RETENTION_DAYS_INCIDENT days... echo set homepath $ADR_HOME; purge -age $AGE_INCIDENT -type incident; | adrci $LOG_FILE 21 elif [[ $ADR_HOME *diag/tnslsnr* ]]; then # 监听器HOME log_message Purging LISTENER ALERT files older than $RETENTION_DAYS_LISTENER_ALERT days... echo set homepath $ADR_HOME; purge -age $AGE_LISTENER_ALERT -type alert; | adrci $LOG_FILE 21 else log_message WARNING: Unknown ADR Home type, skipping specific purge. fi log_message Finished processing $ADR_HOME echo -------------------------------------------------- $LOG_FILE done $ADR_HOMES log_message ADR Purge Cycle Completed Successfully } # 执行主函数 main $脚本亮点解析策略分离脚本根据ADR_HOME的路径特征diag/rdbmsvsdiag/tnslsnr自动应用不同的保留策略。数据库trace文件通常只需要保留一周而监听器日志可以保留更久。健壮性使用了set -o nounset和set -o errexit确保变量未定义或命令执行失败时脚本会立即停止避免在错误状态下继续运行。完整的日志所有操作包括adrci命令的原始输出都被重定向到日志文件/var/log/oracle/adr_purge.log便于事后审计和排错。非交互式执行通过echo command; | adrci的管道方式实现了全自动的非交互式运行这是接入crontab的关键。使用前记得给脚本添加执行权限chmod x purge_adr.sh。首次运行时建议先手动执行一次检查日志输出是否正常。4. 最终自动化与Crontab的完美集成脚本写好了最后一步就是让它定时自动运行彻底解放双手。我们通过Linux的crontab来实现。首先将脚本放在一个合适的目录例如/usr/local/bin/或/home/oracle/scripts/。我习惯放在/opt/oracle/scripts/下。然后编辑oracle用户的crontabcrontab -e添加以下行实现每周日凌晨2点自动执行清理这个时间点通常系统负载较低# Oracle ADR 自动清理任务 0 2 * * 0 /opt/oracle/scripts/purge_adr.sh /dev/null 21如果你希望更频繁地清理比如每天或者想在执行后收到邮件通知需要系统配置好mail可以这样设置# 每天凌晨3点清理并将执行日志通过邮件发送给管理员 0 3 * * * /opt/oracle/scripts/purge_adr.sh 21 | mail -s ADR Purge Report from $(hostname) dba-teamyourcompany.com高级技巧磁盘空间预警触发清理单纯的定时任务可能还不够“智能”。我们可以结合磁盘空间检查实现“按需清理”。下面是一个更高级的脚本片段它会在/u01文件系统使用率超过85%时触发一次额外的、更激进的清理例如只保留3天内的trace文件#!/bin/bash # 磁盘检查触发清理脚本 check_and_purge.sh THRESHOLD85 CURRENT_USAGE$(df -h /u01 | awk NR2 {print $5} | sed s/%//) if [ $CURRENT_USAGE -gt $THRESHOLD ]; then echo Disk usage ($CURRENT_USAGE%) exceeds threshold ($THRESHOLD%). Starting aggressive purge... /var/log/oracle/emergency_purge.log # 执行更激进的清理策略 echo set homepath diag/rdbms/prodcdb/PRODCDB; purge -age 4320 -type trace; | adrci /var/log/oracle/emergency_purge.log 21 # 可以添加更多紧急清理命令... fi然后将这个检查脚本也加入crontab每小时运行一次0 * * * * /opt/oracle/scripts/check_and_purge.sh通过“定时任务”加“事件触发”的双重保障你的Oracle数据库日志管理将真正实现无人化、智能化、策略化。从此深夜的磁盘告警电话将成为历史。你收获的不仅是一个干净整洁的文件系统更是一份从容不迫的运维底气。这套组合拳打下来你会发现Oracle自带的工具链里其实早已藏好了解决常见痛点的“银弹”只是需要我们用心去发现和组合。