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

一、問題

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

環境:github

  • spring boot 1.5.15
  • Centos7.6(aliyun)redis

    二、 問題解析

  1. 爲何須要使用這個/tmp/tomcat*?
  2. 那個 /tmp/tomcat* 目錄爲何不存在?

2.一、 爲何須要使用這個/tmp/tomcat*?

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

2.二、那個 /tmp/tomcat* 目錄爲何不存在?

不存在是由於被Linux 的機制進行清除了。shell

這個機制是什麼原理:
首先咱們得從服務 systemd-tmpfiles-clean 提及。tomcat

[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點執行了一次,咱們繼續看看這個服務對應的執行命令是什麼?springboot

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.timerapp

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 --cleanide

那麼上面這個命令具體又執行了什麼? 咱們在 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天沒有發生變化,也就會被刪除。

3、解決辦法

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

配置參數 :server.tomcat.basedir

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

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

4、spring boot 官方解答

官方相關的 issue :

  • https://github.com/spring-projects/spring-boot/issues/5009
  • https://github.com/spring-projects/spring-boot/issues/9616

在 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

相關文章
相關標籤/搜索