【问题标题】:Creating temporary files in bash在 bash 中创建临时文件
【发布时间】:2012-06-14 12:34:14
【问题描述】:

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

我通常只是将它们命名为我想到的任何名称,例如 tempfile-123,因为它会在脚本结束时被删除。除了覆盖当前文件夹中可能的 tempfile-123 之外,这样做有什么缺点吗?或者以更谨慎的方式创建临时文件有什么好处?

【问题讨论】:

  • 不要使用临时文件。请改用临时目录。并且不要使用 mktemp。在这里查看原因:codeproject.com/Articles/15956/…
  • @ceving 那篇文章是完全错误的,至少在应用于 shell 命令 mktemp 时(与 mktemp 库调用相反)。由于 mktemp 使用限制性 umask 创建文件本身,因此仅当攻击者在与被攻击者相同的帐户下操作时,给定的攻击才有效……在这种情况下,游戏已经丢失。有关 shell 脚本世界的最佳实践,请参阅 mywiki.wooledge.org/BashFAQ/062
  • 你也可以在有tempfile(1)的系统上使用它。

标签: linux bash unix


【解决方案1】:

mktemp(1) 手册页很好地解释了它:

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

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

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

它创建了一个我可以在其中工作的临时目录,并且我可以在其中安全地将实际文件命名为可读且有用的名称。

mktemp 不是标准的,但它确实存在于许多平台上。 “X”通常会被转换成一些随机性,更多的可能会更随机;但是,某些系统(例如,busybox ash)比其他系统更明显地限制了这种随机性


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

【讨论】:

  • 似乎最安全和最跨平台的使用mktemp的方式是与basename结合使用,就像mktemp -dt "$(basename $0). XXXXXXXXXX"一样。如果在没有basename 的情况下使用,您可能会收到类似这样的错误mktemp: invalid template, `/tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXXXXXXX', contains directory separator
  • 忽略他们的拼写错误(额外的空格)。 mktemp -dt "$(basename $0).XXXXXXXXXX" 是正确的方法。
  • @i4niac:你需要引用$0,在OS X领域有很多空间。mktemp -dt "$(basename "$0").XXXXXX"
  • 另外,在脚本执行结束时删除 tempdir 可能会很好:trap "rm -rf $mydir" EXIT
【解决方案2】:

是的,使用mktemp

它将在专为存储临时文件而设计的文件夹中创建一个临时文件,并保证您的名称是唯一的。它输出该文件的名称:

> mktemp
/tmp/tmp.xx4mM3ePQY
>

【讨论】:

    【解决方案3】:

    你可能想看看mktemp

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

    更多详情:man mktemp

    【讨论】:

      【解决方案4】:

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

      临时文件通常创建在所有其他用户和进程具有读写权限的临时目录(例如/tmp)中(任何其他脚本都可以在那里创建新文件)。因此,脚本在创建文件时应该小心,例如使用正确的权限(例如,所有者只读,请参阅:help umask)并且文件名应该不容易猜到(最好是随机的)。否则,如果文件名不是唯一的,它可能会与多次运行的同一脚本产生冲突(例如race condition),或者一些攻击者可能会劫持一些敏感信息(例如,当权限太开放且文件名很容易猜到时)或用他们自己的代码版本创建/替换文件(比如根据存储的内容替换命令或 SQL 查询)。


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

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

      或临时文件:

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

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

      根据man mktemp,我们可以阅读:

      传统上,许多 shell 脚本以 pid 作为后缀的程序名称作为临时文件名。这种命名方案是可预测的,它创造的竞争条件很容易让攻击者获胜。

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

      【讨论】:

      • 它确实改善了答案。不过,我的赞成票已经是你的了。不能再投票了。我的一个建议是解释 ${0##*/}$$ 扩展为什么,或链接到一些有关它的文档。
      【解决方案5】:

      mktemp 可能是最通用的,特别是如果您打算使用该文件一段时间。

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

      $ diff <(echo hello world) <(echo foo bar)
      

      【讨论】:

        猜你喜欢
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-15
        • 1970-01-01
        • 2016-06-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多