慣性聚合 高效追蹤和閱讀你感興趣的部落格、新聞、科技資訊
閱讀原文 在慣性聚合中打開

推薦訂閱源

博客园 - 司徒正美
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
月光博客
月光博客
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI

阮一峰的网络日志

科技爱好者周刊(第 396 期):互联网通信的替代方案 科技爱好者周刊(第 396 期):互联网通信的替代方案 - 阮一峰的网络日志 科技爱好者周刊(第 395 期):软件开发的第三种方式 科技爱好者周刊(第 395 期):软件开发的第三种方式 - 阮一峰的网络日志 科技爱好者周刊(第 393 期):脑腐状态 科技爱好者周刊(第 392 期):axios 投毒与好莱坞式骗术 科技爱好者周刊(第 391 期):AI 的贫富分化 科技爱好者周刊(第 390 期):没有语料,大模型就是智障 套壳中国大模型撑起500亿美元估值?扒一扒 Cursor 的"套壳"疑云 科技爱好者周刊(第 389 期):未来如何招聘程序员 科技爱好者周刊(第 388 期):测试是新的护城河 零安装的"云养虾":ArkClaw 使用指南 科技爱好者周刊(第 387 期):你是领先的 科技爱好者周刊(第 386 期):当外卖员接入 AI 字节全家桶 Seed 2.0 + TRAE 玩转 Skill 科技爱好者周刊(第 385 期):马斯克害怕中国车企吗? 智谱旗舰 GLM-5 实测:对比 Opus 4.6 和 GPT-5.3-Codex 科技爱好者周刊(第 384 期):为什么软件股下跌 科技爱好者周刊(第 383 期):你是第几级 AI 编程 Kimi 的一体化,Manus 的分层 科技爱好者周刊(第 382 期):独立软件的黄昏 AI native Workspace 也许是智能体的下一阶段 科技爱好者周刊(第 381 期):中国 AI 大模型领导者在想什么 科技爱好者周刊(第 380 期):为什么人们拥抱"不对称收益" 科技爱好者周刊(第 379 期):《硅谷钢铁侠》摘录 我如何用 AI 处理历史遗留代码:MiniMax M2.1 升级体验 科技爱好者周刊(第 378 期):预测是新的互联网热点 科技爱好者周刊(第 377 期):14万美元的贫困线 科技爱好者周刊(第 376 期):太空数据中心的争议 科技爱好者周刊(第 375 期):一扇门的 Bug 终于有人做了 Subagent,TRAE 国内版 SOLO 模式来了 科技爱好者周刊(第 374 期):6GHz 的问题 VS Code 使用国产大模型 MiniMax M2 教程 科技爱好者周刊(第 373 期):数据模型是新产品的核心 国产大模型接入 Claude Code 教程:以 Doubao-Seed-Code 为例 科技爱好者周刊(第 372 期):软件界面如何设计 大模型比拼:MiniMax M2 vs GLM 4.6 vs Claude Sonnet 4.5 科技爱好者周刊(第 371 期):一个乐观主义者的专访 科技爱好者周刊(第 370 期):正确的代码高亮 错误处理:异常好于状态码 科技爱好者周刊(第 369 期):Tim 与罗永浩的对谈 科技爱好者周刊(第 368 期):不要这样管理软件团队 一天之内,智谱和 Anthropic 都发了最强编程模型 科技爱好者周刊(第 367 期):Nano Banana 的几个妙用 科技爱好者周刊(第 366 期):旧金山疯狂的 AI 广告 科技爱好者周刊(第 365 期):流量变现正在崩塌 科技爱好者周刊(第 364 期):最难还原的魔方 科技爱好者周刊(第 363 期):最好懂的神经网络解释 科技爱好者周刊(第 362 期):GitHub 工程师谈系统设计 科技爱好者周刊(第 361 期):暗网 Tor 安全吗?
Bash 腳本如何創建臨時文件:mktemp 命令和 trap 命令教程
阮一峰 · 2019-12-29 · via 阮一峰的网络日志

有時,Bash 腳本需要創建臨時文件或臨時目錄。

常見的做法是,自己在/tmp目錄裡面生成一個文件,這樣做有很多弊端。本文介紹如何安全地處理臨時文件。

一、臨時文件的安全問題

直接創建臨時文件,尤其在/tmp目錄裡面,往往會導致安全問題。

首先,/tmp目錄是所有人可讀寫的,任何用戶都可以往該目錄裡面寫文件。創建的臨時文件也是所有人可讀的。


$ touch /tmp/info.txt
$ ls -l /tmp/info.txt
-rw-r--r-- 1 ruanyf ruanyf 0 12月 28 17:12 /tmp/info.txt

上面命令在/tmp目錄直接創建文件,該文件默認是所有人可讀的。

其次,如果攻擊者知道臨時文件的文件名,他可以創建符號鏈接,鏈接到臨時文件,可能導致系統運行異常。攻擊者也可能向腳本提供一些惡意數據。因此,臨時文件最好使用不可預測、每次都不一樣的文件名。

最後,臨時文件使用完畢,應該刪除。但是,腳本意外退出時,往往會忽略清理臨時文件。

二、臨時文件的最佳實踐

腳本生成臨時文件,應該遵循下面的規則。

  • 創建前檢查文件是否已經存在。
  • 確保臨時文件已成功創建。
  • 臨時文件必須有權限的限制。
  • 臨時文件要使用不可預測的文件名。
  • 腳本退出時,要刪除臨時文件(使用trap命令)。

三、mktemp 命令的用法

mktemp命令就是為安全創建臨時文件而設計的。雖然在創建臨時文件之前,它不會檢查臨時文件是否存在,但是它支持唯一文件名和清除機制,因此可以減輕安全攻擊的風險。

直接運行mktemp命令,就能生成一個臨時文件。


$ mktemp
/tmp/tmp.4GcsWSG4vj

$ ls -l /tmp/tmp.4GcsWSG4vj
-rw------- 1 ruanyf ruanyf 0 12月 28 12:49 /tmp/tmp.4GcsWSG4vj

上面命令中,mktemp命令生成的臨時文件名是隨機的,而且權限是隻有用戶本人可讀寫。

Bash 腳本使用mktemp命令的用法如下。


#!/bin/bash

TMPFILE=$(mktemp)
echo "Our temp file is $TMPFILE"

為了確保臨時文件創建成功,mktemp命令後面最好使用 OR 運算符(||),指定創建失敗時退出腳本。


#!/bin/bash

TMPFILE=$(mktemp) || exit 1
echo "Our temp file is $TMPFILE"

為了保證腳本退出時臨時文件被刪除,可以使用trap命令指定退出時的清除操作(詳見後文)。


#!/bin/bash

trap 'rm -f "$TMPFILE"' EXIT

TMPFILE=$(mktemp) || exit 1
echo "Our temp file is $TMPFILE"

四、mktemp 命令的參數

-d參數可以創建一個臨時目錄。


$ mktemp -d
/tmp/tmp.Wcau5UjmN6

-p參數可以指定臨時文件所在的目錄。默認是使用$TMPDIR環境變量指定的目錄,如果這個變量沒設置,那麼使用/tmp目錄。


$ mktemp -p /home/ruanyf/
/home/ruanyf/tmp.FOKEtvs2H3

-t參數可以指定臨時文件的文件名模板,模板的末尾必須至少包含三個連續的X字符,表示隨機字符,建議至少使用六個X。默認的文件名模板是tmp.後接十個隨機字符。


$ mktemp -t mytemp.XXXXXXX
/tmp/mytemp.yZ1HgZV

五、trap 命令的用法

trap命令用來在 Bash 腳本中響應系統信號。

最常見的系統信號就是 SIGINT(中斷),即按 Ctrl + C 所產生的信號。trap命令的-l參數,可以列出所有的系統信號。


$ trap -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT
 4) SIGILL   5) SIGTRAP  6) SIGABRT
 ... ...

trap的命令格式如下。


$ trap [動作] [信號]

上面代碼中,"動作"是一個 Bash 命令,"信號"常用的有以下幾個。

  • HUP:編號1,腳本與所在的終端脫離聯繫。
  • INT:編號2,用戶按下 Ctrl + C,意圖讓腳本中止運行。
  • QUIT:編號3,用戶按下 Ctrl + 斜槓,意圖退出腳本。
  • KILL:編號9,該信號用於殺死進程。
  • TERM:編號15,這是kill命令發出的默認信號。
  • EXIT:編號0,這不是系統信號,而是 Bash 腳本特有的信號,不管什麼情況,只要退出腳本就會產生。

trap命令響應EXIT信號的寫法如下。


$ trap 'rm -f "$TMPFILE"' EXIT

上面命令中,腳本遇到EXIT信號時,就會執行rm -f "$TMPFILE"

trap 命令的常見使用場景,就是在 Bash 腳本中指定退出時執行的清理命令。


#!/bin/bash

trap 'rm -f "$TMPFILE"' EXIT

TMPFILE=$(mktemp) || exit 1
ls /etc > $TMPFILE
if grep -qi "kernel" $TMPFILE; then
  echo 'find'
fi

上面代碼中,不管是腳本正常執行結束,還是用戶按 Ctrl + C 終止,都會產生EXIT信號,從而觸發刪除臨時文件。

注意,trap命令必須放在腳本的開頭。否則,它上方的任何命令導致腳本退出,都不會被它捕獲。

如果trap需要觸發多條命令,可以封裝一個 Bash 函數。


function egress {
  command1
  command2
  command3
}

trap egress EXIT

六、參考鏈接

(完)