好吧,在花了好长时间开发一个准备好测试的脚本之后,我现在了解到目标环境没有mkstemp (我愚蠢地相信每个unix-y操作系统都有),它似乎也没有任何其他常见的临时文件实用程序。如果有任何其他广泛可用的临时文件命令,请告诉我,但我不认为我有任何使用。
因此,这意味着我需要自己实现一种形式的mkstemp。现在最简单的方法是像tmp="/tmp/tmp.$$.$RANDOM"这样的东西,虽然这样做并不能保证文件名之间不会发生冲突,所以我需要为此进行测试,但是问题是,在对文件进行测试和创建文件之间,文件可能会意外地被创建,所以它也可能不是一个合适的方法,至少它本身是这样的。
在过去,我必须自己实现一个等价于lockfile的文件,我可以使用一个临时文件移动到位置,使用mv作为一个欺骗(如果它返回一个错误,那么锁已经存在)。我倾向于认为,如果文件已经存在,我可能可以使用一些操作来执行类似的操作,但我不知道最好的方法是什么。
我知道使用/tmp/tmp.$$.$RANDOM不太可能导致冲突,但如果可以的话,我想要正确地实现这一点,因为脚本需要创建相当多的临时文件,然后移到适当的位置,以后我可能需要在其他脚本中做同样的事情,所以正确地这样做是很好的!
编辑:我刚刚意识到,我指的是mktemp everywhere,而不是mkstemp,这是我真正想要复制的(在这里,文件是为您安全创建的)。我想我已经纠正了错误的说法,请原谅我的困惑!
发布于 2013-08-03 16:44:43
通常,创建临时目录的命令行工具称为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因为这将尝试创建目录(一个原子操作),而不是检查它是否存在并在它生成的名称被接受时失败,所以这个操作是安全的。不过,它很容易受到拒绝服务攻击,攻击者创建许多临时目录就是为了让上面的函数失败。
发布于 2013-08-03 18:02:50
使用@larsman的回答,我想我可能已经找到了自己的答案之一。我不使用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),但我认为上面显示了我正在做的事情,它似乎完全符合我的要求!
因此,谢谢拉斯曼,您的解决方案是mkdtemp的一个很好的替身,上面的方法应该和mkstemp的备用方案一样。我可能会将此标记为答案,但我将保留一段时间,以防有人注意到代码有任何问题。
编辑:不幸的是,此方法需要一个带有不受广泛支持的cp标志的-n版本(不要覆盖),但如果目标文件存在但为空,即使这样也不一定有效,因为cp将认为它已经是具有0状态的有效副本和退出。因此,mkdir可能仍然是更好的选择。
https://stackoverflow.com/questions/18033736
复制相似问题