好的,所以花了很多时间开发一个准备好测试的脚本,我现在已经知道目标环境没有mkstemp
(我愚蠢地认为每个unix-y操作系统都有),它似乎也没有有任何其他常见的临时文件实用程序。如果有任何其他广泛可用的临时文件命令,请告诉我,但我认为我没有任何使用。
所以,这意味着我需要自己实现一种mkstemp
形式。现在最简单的方法是类似tmp="/tmp/tmp.$$.$RANDOM"
,虽然它起作用但并不能保证文件名不会发生冲突,所以我需要对其进行测试,但问题是在测试文件之间并且创建一个文件可能会意外地创建,因此它可能也不是一个合适的方法,至少在它自己的方法上。
在过去,我必须自己实现等效于lockfile
,我可以通过使用mv
作为作弊使用临时文件移动到位(如果它返回错误然后锁已经存在)。我倾向于认为我可以使用某些操作来做类似的事情,如果文件已经存在会失败,但我不确定最好的方法是什么。
我知道使用/tmp/tmp.$$.$RANDOM
不太可能导致冲突,但是如果可以的话我想正确实现这个,因为脚本需要创建大量临时文件然后移入这个地方,我可能需要在以后的其他脚本中做同样的事情,所以做到这一点真好!
编辑:
我刚刚意识到我一直指的是mktemp
到处都是mkstemp
而不是{{1}}这是我真正想复制的那个(为你安全地创建一个文件)。我想我已经纠正了错误的提及,请原谅这种混乱!
答案 0 :(得分:1)
通常,用于创建临时目录的命令行工具称为mktemp
,而不是mkstemp
。我不确定在所有平台上使用它是否安全。如果不是,则可以尝试创建具有严格umask
的目录,并在目录已存在时失败。
mkdtemp() {
old_mask=$(umask)
umask 077
name="/tmp/tmp.$$.$RANDOM"
mkdir "$name" && echo "$name"
retval=$?
umask $old_mask
return $retval
}
用法:
tempdir=$(mkdtemp) || report_failure
由于这会尝试创建目录(原子操作)而不是检查它是否存在并且在生成它所生成的名称时失败,因此此操作是安全的。但是,它容易发生拒绝服务攻击,攻击者创建许多临时目录只是为了让上述功能失败。
答案 1 :(得分:0)
使用@ larsmans的回答我想我可能已经找到了自己的回答。而不是使用mkdir
我将在已知文件上使用cp
,特别是/dev/null
,这有效地创建了一个空文件,但应该原子地这样做!
对于那些感兴趣的人来说,代码的简化版本(请原谅任何拼写错误):
mkstemp() {
umask_old=$(umask)
umask 077
name="/tmp/tmp.$$.$RANDOM"
cp -n /dev/null "$name" 2> /dev/null && echo "$name"
retval=$?
umask "$umask_old"
return "$retval"
}
我已经简化了上面的内容以匹配larsmans的,因为我的实际解决方案将循环,直到创建文件或达到尝试限制,并且我使用的行为更接近mkstemp
实际选择的行为名称(使用带有尾随X的模板),但我认为上面显示了我正在做的事情,它似乎完全符合我的要求!
非常感谢larsmans,您的解决方案是mkdtemp
的一个很好的替代方案,上面的内容应与mkstemp
的替代方案相同。我可能会将此标记为答案,但如果有人注意到代码有任何问题,我会暂时搁置一段时间。
编辑:
不幸的是,这种方法需要cp
版本,并且没有广泛支持的-n
标志(不要覆盖),但即使这样,如果目标文件存在但是为空,也不会一直有效,因为{{1将它视为已经是有效副本并退出状态为cp
。因此0
可能仍然是更好的选择。