在 bash 脚本中创建临时文件客观上有更好的方法吗?
我通常只是将它们命名为任何我想到的名字,比如 temfile-123,因为当脚本结束时它将被删除。除了在当前文件夹中覆盖可能的 temfile-123之外,这样做还有什么缺点吗?或者以更仔细的方式创建临时文件有什么好处吗?
你可能想看看 mktemp
mktemp
Mktemp 实用程序接受给定的文件名模板并覆盖 部分来创建唯一的文件名。模板可以是任何 文件名后面附加了一定数量的“ X”,例如 /tmp/tfile.XXXXXXXXXX。尾随的“ X”被替换为当前进程编号和随机字母的组合。
详情请浏览: Man Mktemp
是的,使用 Mktemp。
它将在用于存储临时文件的文件夹中创建一个临时文件,并保证您有一个唯一的名称。它输出该文件的名称:
> mktemp /tmp/tmp.xx4mM3ePQY >
mktemp(1)的手册页非常好地解释了这一点:
mktemp(1)
传统上,许多 shell 脚本使用程序的名称 将 pid 作为后缀,并将其用作临时文件名 命名方案的竞争条件是可预测的,它创建的竞争条件是 攻击者很容易获胜。一个更安全,但仍然劣势的方法 是使用相同的命名方案创建一个临时目录 这确实可以保证临时文件不会 它仍然允许一个简单的分布式拒绝服务攻击攻击 由于这些原因,建议使用 mktemp。
在脚本中,我调用 mktemp
mydir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")
它创建了一个临时目录,我可以在其中工作,我可以安全地命名实际文件的可读性和有用的东西。
mktemp并不是标准的,但它确实存在于许多平台上。“ X”通常会被转换成某种随机性,更多的可能是更随机的; 然而,一些系统(例如 busybox ash)比其他系统更明显地限制了这种随机性
顺便说一下,安全创建临时文件不仅仅是 shell 脚本编程,它还很重要。这就是为什么 python 有 Tempfile,perl 有 文件: : 临时工,ruby 有 临时档案等等。.
以更仔细的方式创建临时文件有什么好处吗
临时文件通常在临时目录(比如 /tmp)中创建,其中所有其他用户和进程都具有读写权限(任何其他脚本都可以在此创建新文件)。因此,脚本在创建文件时应该小心,比如使用正确的权限(例如,只为所有者读,参见: help umask) ,文件名不应该容易猜测(理想情况下是随机的)。否则,如果文件名不是唯一的,它可能会与多次运行的同一个脚本产生冲突(例如 比赛状态) ,或者一些攻击者可能会劫持一些敏感信息(例如当权限过于开放和文件名很容易猜测时) ,或者创建/替换文件,使用他们自己的代码版本(例如根据存储的内容替换命令或 SQL 查询)。
/tmp
help umask
您可以使用以下方法来创建临时目录:
TMPDIR=".${0##*/}-$$" && mkdir -v "$TMPDIR"
或临时档案:
TMPFILE=".${0##*/}-$$" && touch "$TMPFILE"
然而,它仍然是可预测的,并不被认为是安全的。
根据 man mktemp,我们可以读到:
man mktemp
传统上,许多 shell 脚本使用带有 pid 的程序名作为后缀,并将其用作临时文件名。这种命名方案是可预测的,它创建的竞争条件很容易让攻击者获胜。
因此,为了安全起见,建议使用 mktemp命令创建唯一的临时文件或目录(-d)。
-d
mktemp可能是最通用的,特别是如果您打算使用该文件一段时间。
如果您只是暂时需要该文件作为另一个命令的输入,也可以使用 进程替换运算符进程替换运算符 <(),例如:
<()
$ diff <(echo hello world) <(echo foo bar)
mktemp文件有一些很好的例子。
如果临时文件需要某个后缀(文件扩展名) ,可以执行以下操作
$ myfile=$(mktemp --suffix ".txt") $ echo "$myfile" /tmp/tmp.9T9soL2QNp.txt
如果您不希望创建文件,但只想要一个名称,您可以另外使用 -u/--dry-run标志。
-u/--dry-run
$ myfile=$(mktemp -u --suffix ".txt") $ echo "$myfile" /tmp/tmp.Y8cMDJ1DDr.txt
当使用 -u/--dry-run时,请注意
使用此命令的输出创建新文件本质上是不安全的,因为在生成名称和使用名称之间存在一个时间窗口,其他进程可以使用相同的名称创建对象。
为了扩展以前的答案,这里需要运行 mktemp 还有,确保之后也进行了清理。通常的方法是使用 trap,它允许您设置一个可以在脚本中断时运行的钩子。
trap
Bash 还提供了 EXIT伪信号,这样您就可以设置一个 trap在脚本成功退出时运行,而 ERR在脚本产生错误时触发。(另请参阅 Set-e 在 bash 脚本中是什么意思?了解一些不明显的后果。)
EXIT
ERR
t=$(mktemp -d -p temporary.XXXXXXXXXXXX) || exit trap 'rm -rf "$t"; exit' ERR EXIT # HUP INT TERM : # use "$t" to your heart's content ...
您可能希望在 ERR和 EXIT之外设置其他信号; 显然,kill -9不能被捕获(这就是为什么不应该使用它,除非在紧急情况下)。HUP(信号1)和 INT(信号2)分别在脚本会话挂起或用户按 ctrl-C 时生成。TERM(信号15)是 kill发送的默认信号,请求终止脚本。
kill -9
HUP
INT
TERM
kill
mktemp -p取代了被认为已经过时的 mktemp -t。-d选项指定创建一个目录; 如果您只需要一个临时文件,显然,这是不必要的。
mktemp -p
mktemp -t