lsof +L1 | grep '/var/log' lsof: no pwd entry for UID 10160 lsof: no pwd entry for UID 10160 lsof: no pwd entry for UID 10160 lsof: no pwd entry for UID 10160 sysmonito 1358 root 11w REG 253,0 0 0 62 /var/log/fd_monitor.log (deleted) kube-prox 1602 root 1w REG 253,0 8271424 0 131157 /var/log/kubernetes/kube-proxy.log (deleted) kube-prox 1602 root 2w REG 253,0 8271424 0 131157 /var/log/kubernetes/kube-proxy.log (deleted) kubelet 13265 root 1w REG 253,0 3852482366 0 131076 /var/log/kubernetes/kubelet.log (deleted) kubelet 13265 root 2w REG 253,0 3852482366 0 131076 /var/log/kubernetes/kubelet.log (deleted)
时间: 2025-07-19 21:31:16 浏览: 7
<think>我们有两个任务:
1. 查找/var/log目录下被删除但仍被进程占用的日志文件,并计算它们占用的总空间。
2. 在运行lsof命令时,避免出现'no pwd entry for UID'警告信息。
根据引用[2]提供的改进方案,我们可以选择一种健壮的方法来执行。
步骤:
1. 使用lsof命令查找/var/log目录下被删除的文件(状态为deleted),同时过滤掉'no pwd entry for UID'警告。
2. 计算这些文件占用的总空间(以MB为单位)并输出到日志文件。
3. 根据输出结果,我们可以确定是否有大量空间被已删除但未释放的文件占用。
我们选择引用[2]中的改进方案2:仅忽略特定错误('no pwd entry for UID'),保留其他错误信息。
命令如下:
sudo lsof 2> >(grep -v 'no pwd entry for UID' >&2) | grep '(deleted)' | grep '/var/log' | awk '{sum += $7} END {printf "%.2f MB\n", sum/1024/1024}'
但是,我们也可以将结果输出到日志文件,如:deleted_files_size.log
然而,注意引用[3]中关于FD列的解释:FD列是文件的描述符,而第7列($7)是文件的大小(以字节为单位)?实际上,在lsof的输出中,文件大小通常在第7列(如果使用-l选项,则显示文件大小,但默认情况下不一定显示)。我们需要确认。
根据引用[3]:默认输出中,第7列(如果存在)是文件的大小(SIZE/OFF),但注意不是所有行都有。而且,对于已删除的文件,可能没有大小信息?所以,更可靠的方式是使用lsof的-F选项(输出可解析的格式),但这样处理复杂。
另一种方法:使用lsof的默认输出时,被删除的文件在输出中会标记为(deleted),并且第7列(SIZE/OFF)表示文件大小(如果可用)。但是,对于某些类型的文件(如管道、套接字等)可能没有大小,所以我们需要过滤掉这些。
我们可以尝试:只统计类型为REG(普通文件)的被删除文件。
因此,改进命令:
sudo lsof 2> >(grep -v 'no pwd entry for UID' >&2) | grep -E '/var/log.*deleted' | awk '$4~/REG/ {sum += $7} END {printf "%.2f MB\n", sum/1024/1024}'
解释:
- 使用grep -E匹配包含'/var/log'路径且标记为deleted的行。
- 使用awk过滤第4列(FD列,但实际第4列是FD吗?)—— 注意:lsof的输出列顺序是固定的吗?
实际上,lsof的输出列顺序是固定的吗?引用[3]给出了列的顺序:
COMMAND, PID, TID, USER, FD, TYPE, DEVICE, SIZE/OFF, NODE, NAME
所以,第5列是FD,第7列是SIZE/OFF(大小),第9列是NAME(包含路径和deleted标记)。因此,我们之前用grep过滤NAME列(包含路径和deleted)是可行的,但统计大小应该用第7列(SIZE/OFF)。
但是,注意:第7列可能包含大小,也可能包含偏移量(对于非普通文件)。所以,我们只统计类型为REG(普通文件)的行,并且第5列(FD)应该是以数字或特定字符(如mem)开头?但为了安全,我们根据第4列(TYPE)来判断:如果第4列是REG,则第7列是文件大小。
所以,调整列号:
- 第4列:TYPE
- 第7列:SIZE/OFF(对于普通文件,这是大小;对于其他类型,可能是偏移量)
因此,我们可以这样:
sudo lsof 2> >(grep -v 'no pwd entry for UID' >&2) | awk '$9 ~ /\/var\/log/ && /deleted/ && $4=="REG" {sum += $7} END {printf "%.2f MB\n", sum/1024/1024}'
但是,注意:lsof输出的NAME列(第9列)可能包含空格,所以用正则匹配路径可能不准确。我们可以使用grep先过滤出包含'/var/log'和'(deleted)'的行,然后再用awk处理。
为了确保路径匹配准确,我们使用:
grep '/var/log.*deleted'
但更安全的方式是使用awk匹配整个字段(因为路径在最后一列,但可能包含空格,所以最后一列可能不是完整路径?实际上,lsof输出的最后一列是NAME,包含完整路径,直到行尾。所以,我们可以用正则匹配整个字段。
因此,我们采用分步过滤:
1. 先过滤包含'(deleted)'的行
2. 再过滤包含'/var/log'的行(注意:路径可能在中间,也可能在末尾,但lsof输出的格式是固定的:最后一列是NAME,所以我们可以用$0来匹配整行,因为NAME在最后,所以只要路径出现在NAME列中,就会在整行中)
但是,为了避免匹配到其他列,我们可以指定在NAME列(最后一列)中匹配。
在awk中,最后一列可以用$NF,但注意,如果路径中有空格,那么$NF可能只是路径的最后一部分。所以,我们使用从第9列开始到最后一列。
由于lsof输出列数不固定(因为NAME列可能包含空格),所以更好的方法是使用字段分隔符,但默认是空格,而NAME列可能包含空格,所以不好处理。
因此,我们回到最初的方法:用grep来匹配整行中的字符串。
综合,我们使用:
sudo lsof 2> >(grep -v 'no pwd entry for UID' >&2) | grep '/var/log' | grep '(deleted)' | awk '$4=="REG" {sum+=$7} END {printf "%.2f MB\n", sum/1024/1024}'
注意:这里我们假设第4列是TYPE,第7列是SIZE(单位是字节)。对于普通文件(REG),第7列就是文件大小。
如果我们需要更精确,可以查看lsof的列标题,但通过脚本处理,我们这样设计。
另外,如果文件大小很大,我们可以输出GB。
执行这个命令后,我们得到被删除但仍被占用的日志文件总大小。
如果这个大小很大,说明有进程占用了已删除的文件,导致空间未释放。我们可以通过重启相关服务来释放空间(如系统日志服务rsyslog,或者web服务器如nginx/apache等)。
另外,我们也可以列出这些文件的相关进程,以便决定重启哪些服务。
列出这些进程的命令:
sudo lsof 2> >(grep -v 'no pwd entry for UID' >&2) | grep '/var/log' | grep '(deleted)' | awk '{print $1, $2, $3, $7, $9}'
其中,$1是命令,$2是PID,$3是用户,$7是大小,$9是文件名。
然后,我们可以根据PID重启服务(使用systemctl或者kill命令)。
注意:重启服务会中断服务,请在合适的时间进行。
如果不想重启服务,也可以使用截断文件的方法(但前提是文件描述符还存在,且文件已被删除,所以无法直接截断)。因此,通常重启服务是最简单的方法。
步骤总结:
1. 运行命令计算被删除文件占用的总空间。
2. 如果空间较大,则列出相关进程。
3. 重启相关进程(或服务)以释放空间。
另外,为了避免未来出现此问题,应该配置日志轮转(logrotate)并确保日志文件在轮转后重新打开(通常通过发送信号给进程,如HUP信号,或者配置logrotate的postrotate脚本重启服务)。
根据引用[1],日志文件被删除可能是攻击行为,但如果是管理错误,则按上述方法处理。如果是攻击,则需要进一步的安全检查。
现在,我们编写完整的解决步骤。</think>### 解决 /var/log 下被删除但未释放的日志文件及 UID 警告问题
当 `/var/log` 目录显示空间已满但实际使用量不足时,通常是由于日志文件被删除但进程仍占用所致。同时,运行 `lsof` 命令时可能出现 `no pwd entry for UID` 警告。以下是系统、可靠的解决方案:
#### 步骤1: 精确查找被删除但未释放的文件
使用改进的 `lsof` 命令过滤警告并计算占用空间:
```bash
# 仅忽略 'no pwd entry for UID' 警告,统计占用空间
sudo lsof 2> >(grep -v 'no pwd entry for UID' >&2) |
awk '/\/var\/log/ && /deleted/ && $5=="REG" {sum+=$7; print "PID:"$2, "Size:"$7/1024/1024"MB", "File:"$9} END {printf "Total: %.2f MB\n", sum/1024/1024}' > deleted_files.log
```
命令解析:
- `2> >(grep -v ... >&2)`:过滤特定警告[^2]
- `$5=="REG"`:只统计普通文件(排除管道等特殊文件)[^3]
- `$7`:文件大小列(字节单位)
- 输出示例:
```
PID:1234 Size:1024.00MB File:/var/log/nginx.log (deleted)
Total: 2048.50 MB
```
#### 步骤2: 释放被占用的空间
根据步骤1的 PID 结果处理:
```bash
# 方法1: 安全重启服务(推荐)
sudo systemctl restart $(ps -p 1234 -o comm=)
# 方法2: 清空文件内容(不中断服务)
sudo truncate -s 0 /proc/1234/fd/4 # 需根据 lsof 输出的 FD 列确定文件描述符
```
#### 步骤3: 预防措施
1. **配置日志轮转**
编辑 `/etc/logrotate.conf` 确保日志自动切割:
```conf
/var/log/*.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 root adm # 设置正确权限
postrotate
/usr/bin/systemctl reload rsyslog >/dev/null
endscript
}
```
2. **监控空间使用**
添加 cron 任务:
```bash
# 每天检查空间
echo "0 3 * * * df -h /var/log | awk '{print \$5}' | grep -v Use | cut -d% -f1 | while read usage; do [ \$usage -gt 90 ] && mail -s '日志空间告警' [email protected]; done" | sudo tee /etc/cron.d/log_monitor
```
#### 关键注意事项
1. **禁止直接删除锁定文件**
直接 `rm` 已删除但被占用的文件会导致空间无法释放,甚至引发服务崩溃[^1]。
2. **UID 警告原因**
`no pwd entry for UID` 表示系统找不到该 UID 对应的用户名,通常因:
- 服务账户被删除但进程仍在运行
- Docker 容器使用的临时 UID
可通过 `getent passwd UID` 验证账户是否存在。
3. **安全审计建议**
若发现大量日志被异常删除,需排查入侵可能性[^1]:
```bash
sudo ausearch -k log_deletion -ts today # 检查日志删除审计记录
```
#### 验证效果
```bash
# 检查空间释放情况
df -h /var/log && du -sh /var/log/*
```
> **提示**:对 Docker 容器日志问题,需配置 `daemon.json` 限制日志大小:
> ```json
> { "log-driver": "json-file", "log-opts": {"max-size": "10m", "max-file": "3"} }
> ```
###
阅读全文
相关推荐


















