Spring boot內建Tomcat的臨時目錄被刪除導致檔案上傳不了-問題解析
目錄
- 1、問題
- 2.1、 為什麼需要使用這個
/tmp/tomcat*
? - 2.2、那個
/tmp/tomcat*
目錄為什麼不存在?
- 2.1、 為什麼需要使用這個
- 三、解決辦法
- 修改 springboot 配置,不要在
/tmp
下建立目錄 - 修改 清理 /tmp 下面的檔案的機制
- 修改 springboot 配置,不要在
- 四、spring boot 官方解答
1、問題
在過年後,部分運營人員反應說運營後臺上傳不了圖片,然後檢視日誌,發現報錯內容是/tmp/tomcat* 目錄不存在
環境:
- spring boot 1.5.15
Centos7.6(aliyun)
2、 問題解析
- 為什麼需要使用這個
/tmp/tomcat*
? - 那個
/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.
從上面這個描述我得到了兩個資訊:
- 就是 systemd-tmpfiles 用來建立和清理臨時性的目錄和檔案。
- 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/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.