在bash中创建临时文件


150

有客观的更好的方法在bash脚本中创建临时文件吗?

我通常只要给他们起名就可以使用它们,例如tempfile-123,因为脚本结束后它将被删除。除了覆盖当前文件夹中可能的tempfile-123之外,这样做是否有其他缺点?还是以更谨慎的方式创建临时文件有什么好处?


1
不要使用临时文件。改为使用临时目录。并且不要使用mktemp。看到这里的原因:codeproject.com/Articles/15956/…– ceving 2012
6

17
@ceving至少在将其应用于shell命令mktemp时(与mktemp库调用相对),该文章是完全错误的。由于mktemp会使用限制性umask创建文件本身,因此,只有在攻击者与被攻击者使用相同帐户进行操作的情况下,发出的攻击才有效...在这种情况下,游戏已经丢失。有关shell脚本编写世界的最佳做法,请参阅mywiki.wooledge.org/BashFAQ/062
Charles Duffy

您也可以tempfile(1)在具有此功能的系统上使用。
暂停,直到另行通知。

Answers:


179

mktemp(1)手册页解释了它相当好:

传统上,许多shell脚本使用pid作为后缀来命名程序名称,并将其用作临时文件名。这种命名方案是可预测的,并且它创造的竞争条件很容易使攻击者获胜。一种更安全(尽管仍然较差)的方法是使用相同的命名方案创建一个临时目录。尽管这样做确实可以保证不会破坏临时文件,但它仍然允许进行简单的拒绝服务攻击。由于这些原因,建议使用mktemp代替。

在脚本中,我调用mktemp之类的

mydir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")

这会创建一个我可以使用的临时目录,并可以在其中安全地命名实际文件,使之可读且有用。

mktemp虽然不是标准的,但是它确实存在于许多平台上。“ X”通常会转换为某种随机性,更多的可能更随机。但是,某些系统(例如busybox灰)对该随机性的限制比其他系统更大


顺便说一句,临时文件的安全创建不仅对shell脚本而言重要。这就是为什么python具有tempfile,perl具有File :: Temp,ruby具有Tempfile等的原因。



7
这似乎是最安全和最跨平台的方式来使用mktemp与组合basename,像这样mktemp -dt "$(basename $0). XXXXXXXXXX"。如果不使用,basename可能会收到类似mktemp的错误:无效的模板,`/ tmp / MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXXXXXXX',包含目录分隔符
i4niac

7
忽略它们的错字(多余的空格)。mktemp -dt "$(basename $0).XXXXXXXXXX"是正确的方法。
i4niac 2014年

3
@ i4niac:你需要引用的是$0,有位在OS X的土地有的是mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile

11
在脚本执行结束时删除tempdir也可能会很好:trap "rm -rf $mydir" EXIT
KumZ

43

是的,使用mktemp

它将在用于存储临时文件的文件夹内创建一个临时文件,并保证您具有唯一的名称。它输出该文件的名称:

> mktemp
/tmp/tmp.xx4mM3ePQY
>

19

您可能想看看 mktemp

mktemp实用程序采用给定的文件名模板,并覆盖其中的一部分以创建唯一的文件名。该模板可以是任何文件名,并附加了一些“ X”,例如/tmp/tfile.XXXXXXXXXX。尾随的“ X”将替换为当前进程号和随机字母的组合。

有关更多详细信息:man mktemp


11

以更谨慎的方式创建临时文件有什么好处

临时文件通常/tmp在所有其他用户和进程具有读写访问权限的临时目录(例如中)中创建(任何其他脚本都可以在其中创建新文件)。因此,脚本在创建文件时应格外小心,例如使用具有正确权限的文件(例如,对所有者只读,请参阅:),help umask并且文件名不应轻易猜到(理想情况下是随机的)。否则,如果文件名不是唯一的,则可能与多次运行相同的脚本产生冲突(例如,竞争条件),或者某些攻击者可能劫持一些敏感信息(例如,当权限太开放且文件名容易猜测时),或者使用自己的代码版本创建/替换文件(例如根据所用内容替换命令或SQL查询)已存储)。


您可以使用以下方法来创建临时目录:

TMPDIR=".${0##*/}-$$" && mkdir -v "$TMPDIR"

或临时文件:

TMPFILE=".${0##*/}-$$" && touch "$TMPFILE"

但是,它仍然是可预见的,并不被认为是安全的。

按照man mktemp,我们可以阅读:

传统上,许多shell脚本使用pid作为后缀来命名程序名称,并将其用作临时文件名。这种命名方案是可预测的,并且它创建的竞赛条件很容易使攻击者获胜。

为安全起见,建议使用mktemp命令创建唯一的临时文件或目录(-d)。


2
不完全是问什么。但是,这可能是一个完美的解决方案。
jpbochi '16

1
@jpbochi我已经改进了答案以解决该问题。让我知道是否有帮助。
kenorb

2
确实确实改善了答案。不过,我的赞成票已经是您的了。不能再投票了。我的一个建议是解释内容${0##*/}$$扩展或链接到有关它的一些文档。
jpbochi

0

mktemp 是最通用的工具,尤其是如果您打算使用该文件一段时间。

如果仅临时需要该文件作为另一个命令的输入,则也可以使用过程替换运算符 <(),例如:

$ diff <(echo hello world) <(echo foo bar)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.