<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>/Tmp on Zero Day Notes</title><link>https://blog.5772447.xyz/tags//tmp/</link><description>Recent content in /Tmp on Zero Day Notes</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Fri, 10 Mar 2023 16:20:00 +0000</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags//tmp/index.xml" rel="self" type="application/rss+xml"/><item><title>Linux /tmp 被定时清理致 Java 应用建不了临时文件</title><link>https://blog.5772447.xyz/posts/25cf583a/</link><pubDate>Fri, 10 Mar 2023 16:20:00 +0000</pubDate><guid>https://blog.5772447.xyz/posts/25cf583a/</guid><description>&lt;h2 id="问题背景"&gt;&lt;a href="#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;问题背景&#13;&#10;&lt;/h2&gt;&lt;p&gt;公司微服务集群部署在 CentOS 7 服务器上，Java 应用（Spring Boot）运行时需要在 &lt;code&gt;/tmp&lt;/code&gt; 下创建临时目录用于嵌入式 Tomcat 的文件上传缓存和 JNA 的 native 库解压。此前该环境稳定运行超过一年。&lt;/p&gt;&#10;&lt;h2 id="故障现象"&gt;&lt;a href="#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1" class="header-anchor"&gt;&lt;/a&gt;故障现象&#13;&#10;&lt;/h2&gt;&lt;p&gt;3 月 10 日下午 4:00，运维团队完成了一批安全加固操作（包括配置 systemd-tmpfiles 清理规则）后，陆续有监控告警：订单服务、支付服务和文件上传服务的 error rate 开始上升。&lt;/p&gt;&#10;&lt;p&gt;日志中出现大量：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Caused by: java&lt;span style="color:#f92672"&gt;.&lt;/span&gt;io&lt;span style="color:#f92672"&gt;.&lt;/span&gt;IOException: Permission denied&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at java&lt;span style="color:#f92672"&gt;.&lt;/span&gt;io&lt;span style="color:#f92672"&gt;.&lt;/span&gt;UnixFileSystem&lt;span style="color:#f92672"&gt;.&lt;/span&gt;createFileExclusively(Native Method)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at java&lt;span style="color:#f92672"&gt;.&lt;/span&gt;io&lt;span style="color:#f92672"&gt;.&lt;/span&gt;File&lt;span style="color:#f92672"&gt;.&lt;/span&gt;createTempFile(&lt;span style="color:#a6e22e"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;java:&lt;span style="color:#ae81ff"&gt;2024&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org&lt;span style="color:#f92672"&gt;.&lt;/span&gt;apache&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tomcat&lt;span style="color:#f92672"&gt;.&lt;/span&gt;util&lt;span style="color:#f92672"&gt;.&lt;/span&gt;http&lt;span style="color:#f92672"&gt;.&lt;/span&gt;fileupload&lt;span style="color:#f92672"&gt;.&lt;/span&gt;disk&lt;span style="color:#f92672"&gt;.&lt;/span&gt;DiskFileItem&lt;span style="color:#f92672"&gt;.&lt;/span&gt;write()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Caused by: java&lt;span style="color:#f92672"&gt;.&lt;/span&gt;io&lt;span style="color:#f92672"&gt;.&lt;/span&gt;IOException: No such file &lt;span style="color:#f92672"&gt;or&lt;/span&gt; directory&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at java&lt;span style="color:#f92672"&gt;.&lt;/span&gt;io&lt;span style="color:#f92672"&gt;.&lt;/span&gt;UnixFileSystem&lt;span style="color:#f92672"&gt;.&lt;/span&gt;createFileExclusively(Native Method)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; at org&lt;span style="color:#f92672"&gt;.&lt;/span&gt;springframework&lt;span style="color:#f92672"&gt;.&lt;/span&gt;boot&lt;span style="color:#f92672"&gt;.&lt;/span&gt;web&lt;span style="color:#f92672"&gt;.&lt;/span&gt;embedded&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tomcat&lt;span style="color:#f92672"&gt;.&lt;/span&gt;TomcatServletWebServerFactory&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;所有涉及临时文件创建的操作——文件上传、PDF 导出、Excel 生成——全部失败。&lt;/p&gt;&#10;&lt;h2 id="排查过程"&gt;&lt;a href="#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;排查过程&#13;&#10;&lt;/h2&gt;&lt;h3 id="第一步检查-tmp-状态"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e6%ad%a5%e6%a3%80%e6%9f%a5-tmp-%e7%8a%b6%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;第一步：检查 /tmp 状态&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ls -la /tmp/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwxrwxrwt. &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; Mar &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 16:01 .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dr-xr-xr-x. &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; root root &lt;span style="color:#ae81ff"&gt;280&lt;/span&gt; Mar &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 15:58 ..&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwx------ &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; app app &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt; Mar &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 15:58 hsperfdata_app&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;Spring Boot 默认创建的 &lt;code&gt;/tmp/tomcat.*&lt;/code&gt; 目录全部不存在！&lt;/p&gt;&#10;&lt;h3 id="第二步检查-tmp-的挂载选项"&gt;&lt;a href="#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e6%a3%80%e6%9f%a5-tmp-%e7%9a%84%e6%8c%82%e8%bd%bd%e9%80%89%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;第二步：检查 /tmp 的挂载选项&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ mount | grep /tmp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tmpfs on /tmp type tmpfs &lt;span style="color:#f92672"&gt;(&lt;/span&gt;rw,nosuid,nodev,noexec,relatime&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;&lt;code&gt;noexec&lt;/code&gt; 标志——/tmp 被挂载为禁止执行。Java 的 JNA（Java Native Access）需要在 /tmp 下解压 &lt;code&gt;.so&lt;/code&gt; 文件并加载，&lt;code&gt;noexec&lt;/code&gt; 直接导致这个操作失败。&lt;/p&gt;&#10;&lt;h3 id="第三步追溯变更"&gt;&lt;a href="#%e7%ac%ac%e4%b8%89%e6%ad%a5%e8%bf%bd%e6%ba%af%e5%8f%98%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;第三步：追溯变更&#13;&#10;&lt;/h3&gt;&lt;p&gt;在安全加固中新增了 systemd-tmpfiles 配置：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat /etc/tmpfiles.d/security-cleanup.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 安全加固：每天清理/tmp下超过24小时未访问的文件&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;d /tmp &lt;span style="color:#ae81ff"&gt;1777&lt;/span&gt; root root 1d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;关键问题在这一行 &lt;strong&gt;&lt;code&gt;d /tmp 1777 root root 1d&lt;/code&gt;&lt;/strong&gt;——它告诉 systemd-tmpfiles：&lt;/p&gt;&#10;&#13;&#10; &lt;blockquote&gt;&#13;&#10; &lt;p&gt;如果 &lt;code&gt;/tmp&lt;/code&gt; 不存在，用权限 1777 创建；如果存在，&lt;strong&gt;清空所有超过 1 天的文件和目录&lt;/strong&gt;。&lt;/p&gt;&#10;&#13;&#10; &lt;/blockquote&gt;&#13;&#10;&lt;p&gt;更致命的是，临时目录规则并不是简单的 &lt;code&gt;rm&lt;/code&gt;——它在创建 &lt;code&gt;/tmp&lt;/code&gt; 时&lt;strong&gt;不会自动加上 &lt;code&gt;exec&lt;/code&gt; 选项&lt;/strong&gt;，而运维恰好在 &lt;code&gt;/etc/fstab&lt;/code&gt; 中也添加了 &lt;code&gt;noexec&lt;/code&gt;。&lt;/p&gt;&#10;&lt;h3 id="第四步验证清理动作"&gt;&lt;a href="#%e7%ac%ac%e5%9b%9b%e6%ad%a5%e9%aa%8c%e8%af%81%e6%b8%85%e7%90%86%e5%8a%a8%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;第四步：验证清理动作&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ systemd-tmpfiles --clean /etc/tmpfiles.d/security-cleanup.conf --dry-run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Would remove /tmp/tomcat.8080.1234567890&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Would remove /tmp/tomcat.8443.1234567891&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Would remove /tmp/jna-3506402&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;一次清理会删掉所有正在运行的 Java 应用创建的临时目录。由于 Spring Boot 的 &lt;code&gt;Embedded Tomcat&lt;/code&gt; 在启动时创建了 &lt;code&gt;/tmp/tomcat.*&lt;/code&gt; 目录，运行时持续使用。当 systemd-tmpfiles 在每天的定时任务中执行清理时，会连同正在使用的临时目录一起删除。&lt;/p&gt;&#10;&lt;p&gt;而且 Java 应用尝试重新创建时，因为 &lt;code&gt;noexec&lt;/code&gt; 导致 JNA 的解压-加载流程失败，进而引发连锁失败。&lt;/p&gt;&#10;&lt;h2 id="解决方案"&gt;&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;解决方案&#13;&#10;&lt;/h2&gt;&lt;h3 id="紧急恢复"&gt;&lt;a href="#%e7%b4%a7%e6%80%a5%e6%81%a2%e5%a4%8d" class="header-anchor"&gt;&lt;/a&gt;紧急恢复&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 1. 移除noexec&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mount -o remount,exec /tmp&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 2. 修正systemd-tmpfiles规则&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat &amp;gt; /etc/tmpfiles.d/security-cleanup.conf &lt;span style="color:#e6db74"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;# 只清理/tmp下的临时文件，不删除目录结构&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;# 排除Java和Tomcat的临时目录&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;q /tmp 1777 root root 1d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;x /tmp/tomcat.*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;x /tmp/jna-*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;x /tmp/hsperfdata_*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;EOF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 3. 重启受影响的服务&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;systemctl restart order-service payment-service upload-service&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="长期方案"&gt;&lt;a href="#%e9%95%bf%e6%9c%9f%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;长期方案&#13;&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&#10;&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8&#10;&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;9&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;&#10;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用层指定独立的临时目录，不依赖/tmp&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@Bean&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; TomcatServletWebServerFactory &lt;span style="color:#a6e22e"&gt;tomcatFactory&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; TomcatServletWebServerFactory factory &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; TomcatServletWebServerFactory();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; factory.&lt;span style="color:#a6e22e"&gt;addContextCustomizers&lt;/span&gt;(context &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.&lt;span style="color:#a6e22e"&gt;setTempDir&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; File(&lt;span style="color:#e6db74"&gt;&amp;#34;/opt/app/temp&amp;#34;&lt;/span&gt;));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; factory;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;在服务器上为每个应用创建独立的临时目录 &lt;code&gt;/opt/&amp;lt;app&amp;gt;/temp/&lt;/code&gt;，脱离 &lt;code&gt;/tmp&lt;/code&gt; 依赖。&lt;/p&gt;&#10;&lt;h2 id="根因分析"&gt;&lt;a href="#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90" class="header-anchor"&gt;&lt;/a&gt;根因分析&#13;&#10;&lt;/h2&gt;&lt;p&gt;直接原因：安全加固中同时做了两件事——配置 systemd-tmpfiles 清空 &lt;code&gt;/tmp&lt;/code&gt; 并给 &lt;code&gt;/tmp&lt;/code&gt; 加了 &lt;code&gt;noexec&lt;/code&gt;——导致 Java 应用的临时目录被删除后无法重新创建和加载 native 库。&lt;/p&gt;&#10;&lt;p&gt;深层原因：安全策略变更&lt;strong&gt;未在测试环境验证对业务应用的影响&lt;/strong&gt;。&lt;code&gt;/tmp&lt;/code&gt; 目录被大量 Linux 应用隐式依赖，任何对其的变更都应该做充分的影响评估。&lt;/p&gt;&#10;&lt;h2 id="预防措施"&gt;&lt;a href="#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd" class="header-anchor"&gt;&lt;/a&gt;预防措施&#13;&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;应用临时目录独立化&lt;/strong&gt;：每个微服务使用独立的 &lt;code&gt;/opt/&amp;lt;app&amp;gt;/temp/&lt;/code&gt;，不共用 &lt;code&gt;/tmp&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;安全变更影响评估&lt;/strong&gt;：对基础环境（&lt;code&gt;/tmp&lt;/code&gt;、&lt;code&gt;/etc/fstab&lt;/code&gt;、内核参数等）的变更，必须先在测试环境验证 48 小时&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;禁止盲加 noexec&lt;/strong&gt;：&lt;code&gt;noexec&lt;/code&gt; 对 &lt;code&gt;/tmp&lt;/code&gt; 更安全，但必须确认所有应用兼容后才上线&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;监控 /tmp 异常&lt;/strong&gt;：添加 Prometheus 指标监控 Java 应用是否能正常创建临时文件&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;变更窗口制度&lt;/strong&gt;：基础环境变更必须在低峰窗口执行，且保留回滚 SOP&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结&#13;&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/tmp&lt;/code&gt; 是 Linux 上最&amp;quot;透明&amp;quot;又最危险的目录——几乎所有应用都在用它，但没人专门管理它。运维想做安全加固，方向没错，但 &lt;code&gt;noexec&lt;/code&gt; + 定时清理这组组合拳在非 JNA 环境下可能没事，一碰到 Java 的 native 库加载就炸了。教训是：对共享资源的变更，影响的不是你自己用的那个应用，而是所有依赖它的应用。&lt;/p&gt;&#10;</description></item></channel></rss>