代码之家  ›  专栏  ›  技术社区  ›  skinp

删除意外bash退出中创建的临时文件

  •  69
  • skinp  · 技术社区  · 16 年前

    我正在从bash脚本创建临时文件。我将在处理结束时删除它们,但由于脚本运行了相当长的时间,如果在运行期间杀死它或简单地按CTRL-C键,则不会删除临时文件。

    另外,对于这些临时文件的命名和位置是否有某种最佳实践?
    我目前不确定是否使用:

    TMP1=`mktemp -p /tmp`
    TMP2=`mktemp -p /tmp`
    ...
    

    TMP1=/tmp/`basename $0`1.$$
    TMP2=/tmp/`basename $0`2.$$
    ...
    

    或者也许有更好的解决方案?

    7 回复  |  直到 6 年前
        1
  •  123
  •   Tometzky    4 年前

    我通常创建一个目录,在其中放置所有临时文件,然后立即创建一个退出处理程序,在脚本退出时清理该目录。

    MYTMPDIR="$(mktemp -d)"
    trap 'rm -rf -- "$MYTMPDIR"' EXIT
    

    如果您将所有临时文件置于 $MYTMPDIR ,则在大多数情况下,当脚本退出时,它们都将被删除。但是,使用SIGKILL(kill-9)终止进程会立即终止进程,因此在这种情况下,退出处理程序不会运行。

        2
  •  107
  •   Tometzky    4 年前

    你可以设置一个“ trap

    trap '{ rm -f -- "$LOCKFILE"; }' EXIT
    

    或者,我最喜欢的unix ISM之一是打开一个文件,然后在您仍然打开它时将其删除。文件保留在文件系统中,您可以读取和写入它,但一旦程序退出,文件就会消失。不过,我不知道你在bash里会怎么做。

    顺便说一句:我将给出一个支持mktemp而不是使用您自己的解决方案的论点:如果用户预期您的程序将创建巨大的临时文件,他可能需要设置 TMPDIR 到更大的地方,比如/var/tmp。mktemp认识到,您的手推解决方案(第二个选项)没有。我经常使用 TMPDIR=/var/tmp gvim -d foo bar 例如。

        3
  •  28
  •   Brian Campbell Dennis Williamson    6 年前

    你想使用 trap 用于处理退出脚本或CTRL-C等信号的命令。请参阅 Greg's Wiki 详情请参阅。

    basename $0 这是一个好主意,同时提供一个模板,为足够的临时文件提供空间:

    tempfile() {
        tempprefix=$(basename "$0")
        mktemp /tmp/${tempprefix}.XXXXXX
    }
    
    TMP1=$(tempfile)
    TMP2=$(tempfile)
    
    trap 'rm -f $TMP1 $TMP2' EXIT
    
        4
  •  11
  •   Alex    8 年前

    请记住,选择的答案是 bashism ,表示解决方案为

    trap "{ rm -f $LOCKFILE }" EXIT
    

    只能在bash中工作(如果shell为 dash 还是经典 sh ),但如果您想要兼容性,那么仍然需要枚举所有要捕获的信号。

    还要记住,当脚本退出时,信号“0”(aka EXIT)的陷阱总是被执行,从而导致重复执行 trap 命令

    如果存在退出信号,则不将所有信号堆叠在一行中的原因。

    #!/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

        5
  •  5
  •   hlovdal    16 年前

    与$$一起使用可预测文件名的另一种选择是存在一个巨大的安全漏洞,您永远都不应该考虑使用它。即使它只是你的单用户电脑上的一个简单的个人脚本。这是一个你不应该养成的坏习惯。 BugTraq 充满了“不安全的临时文件”事件。看见 here , here here 有关临时文件安全方面的更多信息。

    我最初想引用不安全的TMP1和TMP2作业,但经过再三考虑,可能会这样 not be a good idea

        6
  •  5
  •   Paul    4 年前

    我不敢相信这么多人认为文件名中没有空格。如果$TMPDIR被分配到“临时目录”,世界将崩溃。

    zTemp=$(mktemp --tmpdir "$(basename "$0")-XXX.ps")
    trap "rm -f ${zTemp@Q}" EXIT
    

    空格和其他特殊字符(如文件名中的单引号和回车符)应该在代码中被视为良好编程习惯的要求。

        7
  •  2
  •   Ruslan Kabalin    13 年前

    我更喜欢使用 tempfile 它以安全的方式在/tmp中创建文件,您不必担心其命名:

    tmp=$(tempfile -s "your_sufix")
    trap "rm -f '$tmp'" exit
    
        8
  •  -5
  •   Mykola Golubyev    16 年前

    您不必费心删除那些用mktemp创建的tmp文件。它们将在以后被删除。