ski*_*inp 86 bash exit temporary-files
我正在从bash脚本创建临时文件.我在处理结束时删除它们,但由于脚本运行了很长时间,如果我在运行期间将其删除或只是CTRL-C,则不会删除临时文件.
有没有办法在执行结束之前捕获这些事件并清理文件?
此外,这些临时文件的命名和位置是否有某种最佳实践?
我目前不确定使用:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
Run Code Online (Sandbox Code Playgroud)
和
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Run Code Online (Sandbox Code Playgroud)
或者是否有更好的解决方案?
Chr*_*Lee 105
我通常会创建一个目录来放置所有临时文件,然后立即创建一个EXIT处理程序,以便在脚本退出时清理此目录.
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
Run Code Online (Sandbox Code Playgroud)
如果您将所有临时文件放在下面$MYTMPDIR,那么在大多数情况下,当您的脚本退出时,它们都将被删除.使用SIGKILL杀死进程(kill -9)会立即终止进程,因此在这种情况下您的EXIT处理程序将无法运行.
Pau*_*lin 82
您可以设置一个" 陷阱 "在退出时执行或在control-c上执行清理.
trap "{ rm -f $LOCKFILE; }" EXIT
Run Code Online (Sandbox Code Playgroud)
或者,我最喜欢的一个unix-isms是打开一个文件,然后在你打开文件时删除它.该文件保留在文件系统上,您可以读取和写入该文件,但是一旦程序退出,该文件就会消失.但是不知道你怎么在bash中这样做.
BTW:我将支持mktemp而不是使用你自己的解决方案的一个论点:如果用户预期你的程序将创建巨大的临时文件,他可能想要设置TMPDIR更大的地方,比如/ var/tmp.mktemp认识到,您的手动解决方案(第二个选项)没有.TMPDIR=/var/tmp gvim -d foo bar例如,我经常使用.
Bri*_*ell 22
您希望使用trap命令来处理退出脚本或CTRL-C之类的信号.有关详细信息,请参阅" 高级Bash脚本编制指南 ".
对于你的临时文件,使用basename $0是一个好主意,并提供一个模板,为足够的临时文件提供空间:
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap 'rm -f $TMP1 $TMP2' EXIT
Run Code Online (Sandbox Code Playgroud)
避免假设变量的值在某个超远的时间永远不会改变(特别是如果这样的错误会引发错误)。
如果适用于您的代码,请立即使 trap 扩展变量的值。传递给trap单引号的任何变量名称都会延迟其值的扩展,直到捕获之后。
避免假设文件名不包含任何空格。
请使用 Bash${VAR@Q}或$(printf '%q' "$VAR")克服由空格和其他特殊字符(例如文件名中的引号和回车符)引起的问题。
zTemp=$(mktemp --tmpdir "$(basename "$0")-XXX.ps")
trap "rm -f ${zTemp@Q}" EXIT
Run Code Online (Sandbox Code Playgroud)
请记住,选择的答案是bashism,这意味着解决方案
trap "{ rm -f $LOCKFILE }" EXIT
Run Code Online (Sandbox Code Playgroud)
只能在bash中工作(如果你是dash经典的话,它不会捕获Ctrl + c sh),但是如果你想要兼容性,那么你仍然需要枚举你想要捕获的所有信号.
还要记住,当脚本退出陷阱时,始终执行信号"0"(也称为EXIT),导致trap命令的双重执行.
如果存在EXIT信号,则不会将所有信号堆叠在一条线上的原因.
为了更好地理解它,请查看以下脚本,这些脚本可以在不进行更改的情
#!/bin/sh
on_exit() {
echo 'Cleaning up...(remove tmp files, etc)'
}
on_preExit() {
echo
echo 'Exiting...' # Runs just before actual exit,
# shell will execute EXIT(0) after finishing this function
# that we hook also in on_exit function
exit 2
}
trap on_exit EXIT # EXIT = 0
trap on_preExit HUP INT QUIT TERM STOP PWR # 1 2 3 15 30
sleep 3 # some actual code...
exit
Run Code Online (Sandbox Code Playgroud)
这个解决方案将为您提供更多控制,因为您可以在最终退出(preExit函数)之前运行实际信号时运行一些代码,如果需要,您可以在实际EXIT信号上运行一些代码(退出的最后阶段)