如何将日志文件链接到 /dev/null 并自动恢复使用的空间

如何将日志文件链接到 /dev/null 并自动恢复使用的空间

我有一个变得很大的日志文件。我能从中得到的信息可以忽略不计。

我想将它链接到/dev/null.然而,即使它被“删除”(见下面lsof的输出),它也会消耗我所有的硬盘空间。

我可以使用以下方法截断它:

: > "/proc/$pid/fd/$fd"
# for instance:
: > "/proc/2456/fd/2"

不幸的是,系统上的某些进程在硬盘已满时会暂停,必须手动重新启动(并且我想避免进程被暂停)。

有没有办法在文件变得太大时自动截断文件(例如,当它消耗超过 1G 时?)

lsof输出:

program  2456 user    2w   REG    8,5 441433300992     0 21365598 /home/user/file (deleted)

答案1

仅当不再引用文件时,文件的内容才会被删除。对文件的引用可以是目录条目或打开的文件句柄。当您删除某个进程(rm此处为记录该文件的进程)仍然打开的文件(例如使用命令)时,该文件的内容将保留,直到该进程关闭该文件。

摆脱旧日志的最直接方法是

  1. 将文件移动到另一个名称,例如mv foo.log foo.log.old
  2. 指示进程重新打开其日志文件。如果该进程无法做到这一点,请重新启动它。
  3. 删除现已关闭的旧日志文件 ( rm foo.log.old)。

该程序对数旋转自动化此机制,并且可以配置旧日志的保留天数。它还可以压缩旧日志。

对于步骤 2,如果您无法重新启动程序并且无法重新打开其日志文件,您可以尝试使用调试器强制使其重新打开日志文件。但是,请注意,如果程序保留有关现在变得不一致的日志文件的信息,则可能会使程序崩溃。概念验证(请注意,很多事情可能会出错;如果有疑问,请不要这样做):

gdb -n $pid -batch -x /dev/stdin <<EOF
call close(2)
call open("/path/to/foo.log", 1)
EOF

如果您不关心任何日志,则释放一些磁盘空间的另一种粗略方法是截断文件。日志记录进程将继续在文件中的同一位置写入,但该文件将成为稀疏文件。如果从头开始读取文件,您将得到空字节,但这些空字节仅占用磁盘上的几 kB。

dd if=/dev/null of=/path/to/foo.log

答案2

重新启动program以释放已删除的文件。进行调查logrotate等以正确管理日志数据,或调整程序以发出更少的日志消息。

答案3

当您删除文件时,您实际上并没有“删除”它。你把它取消链接。最终结果是打开日志文件的程序仍然可以访问日志文件,直到关闭它(这对于日志文件来说很少见)。

现在,为了正确解决您的问题,您需要研究日志轮换和日志过滤。

日志轮转将允许您根据一组规则进行归档、压缩和删除。例如,所有早于一天的条目都会被压缩,所有超过 7 天的条目都会被删除。

日志过滤只是减少进入日志的“东西”的数量。有些程序在程序端实现过滤,其他程序在记录器端实现过滤。例如,如果您使用 syslogd,您可以告诉它过滤掉所有事情上的非关键消息(再次举例)。

要快速解决问题,请重新启动服务,查明它是否响应非常常见的信号 SIGUSR1 和 SIGHUP,然后发送该信号,或者重新启动计算机。

答案4

如果日志文件是通过输出到stderr或来创建的stdout,并且如果您可以控制创建日志文件的程序(我们称之为bar)的启动方式,请以 启动它bar &>/dev/null,这会将所有标准输出或错误消息重定向到 /开发/空。

或者,(我知道这确实是不好的做法,但至少它会起作用)设置一个每小时的 cron 作业来终止创建日志的程序,删除日志文件,然后启动程序备份,前提是该程序不是对系统运行至关重要。再次假设该程序的名称是bar,则执行此操作的方法是echo "* 0 0 0 0 \"/bin/killall [offending program]; /bin/rm [offending log]; [command to run program];\" 1>[crontab location]"

请注意,方括号用于表示占位符,不应出现在输入的命令中。

再次,请注意,第二种解决方案确实是不好的做法,总的来说只是绷带修复......所以使用它需要您自担风险。

相关内容