当前位置:首页>Linux>Linux线上配置被改了找不到人?教你一招让所有操作留痕

Linux线上配置被改了找不到人?教你一招让所有操作留痕

  • 2026-09-07 22:54:36
Linux线上配置被改了找不到人?教你一招让所有操作留痕

服务器被误操作了,不知道谁干的?

线上配置被改了,找不到记录?

出了安全事故,审计要求拿出操作日志?

——Linux默认的 history 命令远远不够。

这篇文章教你两步搞定:操作日志采集 + 日志自动轮转,5分钟部署,从此服务器操作有据可查。

一、默认history为啥不够用?

Linux自带的history命令,问题一大堆:

❌ 不记录时间 —— 默认只有命令本身,没有执行时间。看到一条 rm -rf /,你不知道是昨天还是半年前执行的

❌ 不记录来源IP —— 多人通过SSH登录同一台服务器,你分不清哪条命令是谁从哪台机器上执行的

❌ 不记录工作目录 —— 看到 rm -rf data,不知道是在 /tmp 还是 / 下执行的,性质完全不同

❌ 用户可以删除 —— history -c 一键清空,恶意操作者可以轻松抹掉痕迹

我们要实现的效果:

2024-12-17 16:34:52 | user=root | from=10.1.1.1 | path=/root | cmd:cat /etc/profile

每条命令自动记录:时间、用户、来源IP、工作目录、执行命令——清清楚楚,谁也删不掉。

二、第一步:配置操作日志采集

核心思路:修改 /etc/profile,利用 PROMPT_COMMAND 在每次命令执行后自动记录日志。

🔧 一键部署脚本

保存为 setup_history_log.sh,直接执行:

#!/bin/bash# 检查 /etc/profile 中是否已经存在 history.logif grep -q 'history.log' /etc/profile; then    echo "提示: /etc/profile 已包含 history.log 配置,未做任何操作。"else    cat <<'EOF' >> /etc/profileexport HISTTIMEFORMAT="`whoami` %Y-%m-%d %H:%M:%S "export HISTORY_FILE=/var/log/history.logexport PROMPT_COMMAND='{ date "+%Y-%m-%d %T | user=$(whoami) | from=$(echo $SSH_CLIENT | awk "{print \$1}") | path=$(pwd) | cmd:$(history 1 | { read x y z o; echo "$o"; })"; } >> $HISTORY_FILE'HISTCONTROL=ignorespace:ignoredupsexport PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROLEOF    echo "配置已成功添加到 /etc/profile"fi

📖 逐行解读配置

export HISTTIMEFORMAT="`whoami` %Y-%m-%d %H:%M:%S "

history命令时间格式:让history输出时显示"用户名 + 年月日时分秒"。只影响history显示,不影响日志文件

export HISTORY_FILE=/var/log/history.log

日志文件路径:所有操作日志统一写入这个文件。独立于 ~/.bash_history,用户删不了

export PROMPT_COMMAND='{ date ... } >> $HISTORY_FILE'

核心机制:Bash每次显示提示符前自动执行PROMPT_COMMAND。我们在里面拼装一条日志(时间|用户|来源IP|目录|命令)追加到文件。用户无感知,也绕不过去

HISTCONTROL=ignorespace:ignoredups

history过滤规则:ignorespace = 命令前加空格不记录(敏感操作如输密码时有用);ignoredups = 连续重复命令只记一次

⚙️ 配置生效

# 执行脚本bash setup_history_log.sh# 让配置立即生效source /etc/profile# 创建日志文件并设置权限(所有用户可写,确保审计覆盖)touch /var/log/history.logchmod 666 /var/log/history.log# 验证:随便执行几条命令,然后查看日志cat /var/log/history.log

⚡ 关键理解:PROMPT_COMMAND

PROMPT_COMMAND是Bash的一个特殊变量——每次命令执行完毕、显示新提示符之前,Bash都会自动执行它里面的内容。

我们利用这个机制,把"记录日志"的动作嵌入到Bash的执行流程中。用户敲任何命令,日志就自动追加了,完全不需要主动操作。

注意:此配置对所有登录用户生效(包括新建用户),因为它写在 /etc/profile 中。

三、第二步:配置日志自动切割

日志文件会越来越大,不切割的话 /var/log/history.log 几个月就能长到好几个GB。用logrotate自动轮转,省心省力。

🔧 一键部署脚本

保存为 setup_logrotate.sh,直接执行:

#!/bin/bashTARGET_FILE="/etc/logrotate.d/history"if [ -f "$TARGET_FILE" ]; then    if grep -q '/var/log/history.log' $TARGET_FILE; then        echo "提示: 已包含历史日志配置,未做任何修改。"        exit 0    fielse    touch $TARGET_FILEficat <$TARGET_FILE/var/log/history.log {    missingok    ifempty    monthly    dateext    create 666 root root    copytruncate    rotate 3}EOFchmod 644 $TARGET_FILEecho "配置已成功添加到 $TARGET_FILE"

📖 逐行解读配置

参数
含义
说明
missingok
日志不存在不报错
首次部署时日志文件可能还没创建,避免logrotate报错
ifempty
空文件也轮转
即使日志为空也按计划切割,保持轮转周期一致
monthly
每月轮转一次
可根据日志量调整为 daily / weekly。日志量大的建议 weekly
dateext
用日期做后缀
切割后文件名如 history.log-20241201,一目了然
create 666 root root
新建日志文件权限
轮转后创建新的空日志,权限666确保所有用户可写
copytruncate
复制后截断
先复制当前日志到备份文件,再清空原文件。不需要重启服务
rotate 3
保留3份备份
保留最近3个月的日志。审计要求高可调大

📁 轮转效果

[root@server log]# ls /var/log/history.log*history.log                ← 当前日志history.log-20240901    ← 9月归档history.log-20241001    ← 10月归档history.log-20241101    ← 11月归档history.log-20241201    ← 12月归档(rotate 3后最早的会被删除)

💡 copytruncate vs create

copytruncate:复制当前日志 → 清空原文件 → 完成。不需要通知任何进程,适合我们这种"自己写日志"的场景。

create(不加copytruncate):重命名当前日志 → 创建新文件 → 需要通知进程重新打开文件(用postrotate)。适合nginx、mysql等有自己日志系统的服务。

我们这里用 copytruncate 是正确选择——因为 PROMPT_COMMAND 是以追加模式打开文件,不需要重新通知。

四、你可能有的疑问

❓ 用户删掉 /var/log/history.log 怎么办?

两个防护:

1️⃣ 文件权限加固——用 chattr +a /var/log/history.log 设置"只允许追加"属性,root也删不掉(除非先 chattr -a 解除)

2️⃣ 日志远程备份——用rsyslog把日志实时转发到日志服务器,本地删了远程还有。这是企业级审计的标准做法

❓ 666权限会不会有安全问题?

666意味着所有用户可读可写,确实存在信息泄露风险——普通用户能看到root执行了什么命令。如果安全要求高,可以改为 600 root root,配合sudo让普通用户通过审计命令查看(但写入需要特殊处理)。企业环境建议用auditd替代或搭配rsyslog远程集中存储。

❓ 和auditd有什么区别?用哪个?

对比项
本文方案(PROMPT_COMMAND)
auditd
层级
Bash命令行
内核级
记录范围
Bash命令
系统调用、文件访问、权限变更
可绕过性
理论上可绕过
不可绕过
适用场景
中小团队日常运维追溯
等保合规、正式安全审计

简单说:日常运维追溯用本文方案够了;要过等保、做正式安全审计,上auditd。两者可以共存。

❓ rotate 3只保留3个月,审计要求保存更久怎么办?

直接改数字——rotate 12 就是保留12个月。同时注意磁盘空间:一个月的日志大约几十MB到几百MB(取决于服务器操作频率)。也可以把轮转周期改为 daily + rotate 90,按天切割保留90天,粒度更细。

❓ 已经在运行的服务器,部署后需要重启吗?

不需要重启服务器。执行 source /etc/profile 后,当前会话立即生效。但已登录的其他会话需要重新登录才会加载新配置。如果想让所有人立即生效,可以发个通知让大家重新登录,或者等到自然登出。

❓ 命令前加空格真的不会被记录吗?

ignorespace只影响history命令的输出,不影响PROMPT_COMMAND写入日志文件。也就是说,即使命令前加空格,/var/log/history.log 里还是会记录——这也正是我们想要的,审计不能留死角。

五、部署验证清单

✅ 1. 执行部署脚本,确认输出"配置已成功添加"

✅ 2. source /etc/profile 生效

✅ 3. cat /etc/profile 确认配置已写入

✅ 4. 随便敲几条命令,cat /var/log/history.log 确认有记录

✅ 5. cat /etc/logrotate.d/history 确认轮转配置

✅ 6. logrotate -d /etc/logrotate.d/history 模拟运行确认无报错

两步配置,5分钟搞定:

第一步:修改 /etc/profile,用 PROMPT_COMMAND 自动记录每条命令(时间|用户|来源IP|目录|命令)

第二步:配置 logrotate,每月自动切割日志,保留最近3份

进阶:chattr +a 防删除 + rsyslog 远程备份 + auditd 内核审计

从此服务器操作有据可查,谁也赖不掉。

最新文章

随机文章