背景

最近在java代码中,升级了一些二方库和三方库的版本。在现网运行了一段时间之后,服务突然出现异常。

查看错误日志,是因为 File not found or permission denied 引起的,是一个升级过的二方库报的错。尝试重启服务,重启之后没有出现错误,业务恢复正常

问题定位

仔细查看这个升级后的二方库的代码,发现提示 File not found or permission denied 的文件,应该是在 /tmp 目录下的。服务重启之后,/tmp 目录是有这个文件的。尝试把这个文件删除,再去构造请求触发代码逻辑,查看日志文件,是会报相同的错误。

从笔者的认知角度里,/tmp 目录下应该是所有用户都可以读写的,如果一个用户创建了文件,理论上不太可能出现 permission denied 问题。尝试Google “tmp下文件被自动清理”,果然找到了相关原因(Google大法好):centos操作系统有一个自动清理临时文件的 systemd-tmpfiles 服务,会自动清理/tmp 下超过10天的内容

好吧,应该是找到根因了,接下来稍微学习并验证一下,是不是这个 systemd-tmpfiles 导致的

systemd-tmpfiles 服务

先贴几个链接:

为了方便管理(创建、删除)操作系统中的临时目录和文件,redhat和fedora提供了 systemd-tmpfiles 服务

systemd-tmpfiles 主要有以下3个服务:

  • systemd-tmpfiles-setup.service
  • systemd-tmpfiles-setup-dev.service
  • systemd-tmpfiles-clean.service。它并不是一直运行着的,而是通过 systemd-tmpfiles-clean.timer 来定时启动

相关的配置文件也有3个地方:

/etc/tmpfiles.d/*.conf
/run/tmpfiles.d/*.conf
/usr/lib/tmpfiles.d/*.conf

/tmp目录的清理规则主要取决于/usr/lib/tmpfiles.d/tmp.conf文件的设定,查看笔者 centos8 的配置文件:

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# See tmpfiles.d(5) for details

# Clear tmp directories separately, to make them easier to override
q /tmp 1777 root root 10d
q /var/tmp 1777 root root 30d

# Exclude namespace mountpoints created with PrivateTmp=yes
x /tmp/systemd-private-%b-*
X /tmp/systemd-private-%b-*/tmp
x /var/tmp/systemd-private-%b-*
X /var/tmp/systemd-private-%b-*/tmp

# Remove top-level private temporary directories on each boot
R! /tmp/systemd-private-*
R! /var/tmp/systemd-private-*

可以看到 /tmp 目录下的文件是保留10天的,10天后文件会被删除(下面exclude的文件除外)

systemd-tmpfiles 功能测试

修改/usr/lib/tmpfiles.d/tmp.conf,把 10d 修改为 60s

在 /tmp 目录下创建 test.txt 文件,60s 之后,执行 systemctl start systemd-tmpfiles-clean.service,查看文件是否还在。测试结果如下图所示

systemd-tmpfiles-test.png