我正在从bash脚本创建临时文件.我在处理结束时删除它们,但由于脚本运行了很长时间,如果我在运行期间将其删除或只是CTRL-C,则不会删除临时文件.
有没有办法在执行结束之前捕获这些事件并清理文件?
此外,这些临时文件的命名和位置是否有某种最佳实践?
我目前不确定使用:
TMP1=`mktemp -p /tmp` TMP2=`mktemp -p /tmp` ...
和
TMP1=/tmp/`basename $0`1.$$ TMP2=/tmp/`basename $0`2.$$ ...
或者是否有更好的解决方案?
我通常会创建一个目录来放置所有临时文件,然后立即创建一个EXIT处理程序,以便在脚本退出时清理此目录.
MYTMPDIR=$(mktemp -d) trap "rm -rf $MYTMPDIR" EXIT
如果您将所有临时文件放在下面$MYTMPDIR
,那么在大多数情况下,当您的脚本退出时,它们都将被删除.使用SIGKILL杀死进程(kill -9)会立即终止进程,因此在这种情况下您的EXIT处理程序将无法运行.
您可以设置一个" 陷阱 "在退出时执行或在control-c上执行清理.
trap "{ rm -f $LOCKFILE; }" EXIT
或者,我最喜欢的一个unix-isms是打开一个文件,然后在你打开文件时删除它.该文件保留在文件系统上,您可以读取和写入该文件,但是一旦程序退出,该文件就会消失.但是不知道你怎么在bash中这样做.
BTW:我将支持mktemp而不是使用你自己的解决方案的一个论点:如果用户预期你的程序将创建巨大的临时文件,他可能想要设置TMPDIR
更大的地方,比如/ var/tmp.mktemp认识到,您的手动解决方案(第二个选项)没有.TMPDIR=/var/tmp gvim -d foo bar
例如,我经常使用.
您希望使用trap命令来处理退出脚本或CTRL-C之类的信号.有关详细信息,请参阅" 高级Bash脚本编制指南 ".
对于你的临时文件,使用basename $0
是一个好主意,并提供一个模板,为足够的临时文件提供空间:
tempfile() { tempprefix=$(basename "$0") mktemp /tmp/${tempprefix}.XXXXXX } TMP1=$(tempfile) TMP2=$(tempfile) trap 'rm -f $TMP1 $TMP2' EXIT
请记住,选择的答案是bashism
,这意味着解决方案
trap "{ rm -f $LOCKFILE }" EXIT
只能在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
这个解决方案将为您提供更多控制,因为您可以在最终退出(preExit
函数)之前运行实际信号时运行一些代码,如果需要,您可以在实际EXIT信号上运行一些代码(退出的最后阶段)