Spring boot內置Tomcat的臨時目錄被刪除導致文件上傳不了-問題解析


1、問題

在過年后,部分運營人員反應說運營后台上傳不了圖片,然后查看日志,發現報錯內容是/tmp/tomcat* 目錄不存在

環境:

  • spring boot 1.5.15
  • Centos7.6(aliyun)

2、 問題解析

  1. 為什么需要使用這個/tmp/tomcat*?
  2. 那個 /tmp/tomcat* 目錄為什么不存在?

2.1、 為什么需要使用這個/tmp/tomcat*?

默認情況下,spring boot 的內置 Tomcat ,會在/tmp創建兩個目錄 /tmp/tomcat*,這個目錄用於存儲編譯的JSP 和 上傳的文件。

2.2、那個 /tmp/tomcat* 目錄為什么不存在?

不存在是因為被Linux 的機制進行清除了。

這個機制是什么原理:
首先我們得從服務 systemd-tmpfiles-clean 說起。

[root@djx ~]# systemctl  status  systemd-tmpfiles-clean
● systemd-tmpfiles-clean.service - Cleanup of Temporary Directories
   Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.service; static; vendor preset: disabled)
   Active: inactive (dead) since Tue 2020-02-25 09:10:36 CST; 12h ago
     Docs: man:tmpfiles.d(5)
           man:systemd-tmpfiles(8)
  Process: 21819 ExecStart=/usr/bin/systemd-tmpfiles --clean (code=exited, status=0/SUCCESS)
 Main PID: 21819 (code=exited, status=0/SUCCESS)

Feb 25 09:10:36 djx systemd[1]: Starting Cleanup of Temporary Directories...
Feb 25 09:10:36 djx systemd[1]: Started Cleanup of Temporary Directories.

我們可以看到這個服務今天上午 9點執行了一次,我們繼續看看這個服務對應的執行命令是什么?

cat  /usr/lib/systemd/system/systemd-tmpfiles-clean.service
#  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.

[Unit]
Description=Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target time-sync.target
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --clean
IOSchedulingClass=idle

我們先記住這個執行命令是/usr/bin/systemd-tmpfiles --clean,我們再來關心下,與這個服務相關的定時器 /usr/lib/systemd/system/systemd-tmpfiles-clean.timer

cat  /usr/lib/systemd/system/systemd-tmpfiles-clean.timer 
#  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.

[Unit]
Description=Daily Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)

[Timer]
OnBootSec=15min
OnUnitActiveSec=1d

我們從這知道在啟動后的15分鍾或者距離上一次執行一天 會執行我們上面的命令/usr/bin/systemd-tmpfiles --clean

那么上面這個命令具體又執行了什么? 我們在 man systemd-tmpfiles 中找到了一些東西。

DESCRIPTION
       systemd-tmpfiles creates, deletes, and cleans up volatile and temporary files and directories, based on the configuration file format and location
       specified in tmpfiles.d(5).

       If invoked with no arguments, it applies all directives from all configuration files. If one or more filenames are passed on the command line, only
       the directives in these files are applied. If only the basename of a configuration file is specified, all configuration directories as specified in
       tmpfiles.d(5) are searched for a matching file.

從上面這個描述我得到了兩個信息:

  1. 就是 systemd-tmpfiles 用來創建和清理臨時性的目錄和文件。
  2. systemd-tmpfiles 會從 tmpfiles.d 中獲取配置文件。

當然我們在 man systemd-tmpfiles 中還可以了解到一些參數命令。

我們接着去看 tmpfiles.d, 我們在 man tmpfiles.d中可以看到 tmpfiles.d 的作用就是用於清理臨時文件和目錄的配置。 我們還可以看到它的配置存儲於

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

在這里我們還可以看到配置文件里面的相關注解。

接下來我們去上面列出的三個目錄里面找找看有沒有相關清理/tmp的東西。
最后在 /usr/lib/tmpfiles.d/tmp.conf 里面找到了,

cat /usr/lib/tmpfiles.d/tmp.conf 
#  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
v /tmp 1777 root root 10d
v /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

我們可以看其中的兩個配置

v /tmp 1777 root root 10d  # 就是當 /tmp 目錄不存在的時間進行創建(權限為777,用戶和用戶組為root),並清理/tmp下超過10天的文件。
x /tmp/systemd-private-%b-*  # 忽略清理的目錄
X /tmp/systemd-private-%b-*/tmp # 這個只忽略目錄,但不忽略該目錄下面的內容

意思就是 清理/tmp 目錄下超過10天沒有變化的文件,但不清理/tmp/systemd-private-%b-*/tmp/systemd-private-%b-*/tmp.
總結 系統會自動進行清理 /tmp 目錄下10天沒有變化的文件和目錄

過年期間我們的 Tomcat 生成的目錄如果10天沒有發生變化,也就會被刪除。

三、解決辦法

修改 springboot 配置,不要在/tmp 下創建目錄

配置參數 :server.tomcat.basedir

修改 清理 /tmp 下面的文件的機制

/usr/lib/tmpfiles.d/tmp.conf 下面增加一個 x /tmp/tomcat*

四、spring boot 官方解答

官方相關的 issue :

https://github.com/spring-projects/spring-boot/issues/9616,
在最底部我們可以

You can see the list of releases that contain the fix in the commit that closed this issue. In the 2.1.x line it was fixed in 2.1.4.

看到 2.1.4 版本已經解決了該問題。在 1系列的版本中,我們可以看到在 1.5.20 中也修復了,github對應的提交記錄

參考:https://www.cnblogs.com/samtech/p/9490166.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM