如何可靠地删除脚本中创建的所有临时文件?

如何可靠地删除脚本中创建的所有临时文件?

是否可以捕获函数的退出/返回?对于一个程序,我可以这样做

trap -- "clean_this" EXIT

这将在程序退出时执行该函数clean_this。我希望在退出函数时执行类似操作。

function myfunc() {
  echo "I'm a function"
}

myfunc &
wait $!

我在子 shell 中执行该函数,我想捕获它的退出/返回。这可能吗?


编辑1

这是我的目的

我有一个用于管理临时文件的脚本:

cat tempfiles.sh

## List of temp files
tmp_tmp_files=()

## Adds a file to the list of temp files
function tmp_add_file() {
  tmp_tmp_files+=("$1")
}

## Resets the list of temp files
function tmp_reset_files() {
  tmp_tmp_files=()
}

## Removes the list of temp files 
function tmp_rm_all() {
  rm -f "${tmp_tmp_files[@]}"
}

## Removes all temp files on exit and sigint
trap "tmp_rm_all" EXIT SIGINT

这是我的主要脚本:

cat mscript.sh

source tempfiles.sh

## ## Creates a temp file and writes in it
mfunc() {
  local tempfile=$(mktemp)
  tmp_add_file $tempfile
  echo "something" >> $tempfile
  echo "($BASHPID) - tempfiles: ${tmp_tmp_files[@]}"
}

## Creates a temp file in main shell
mfunc

## Creates a temp file in a subshell
(mfunc)

我调用主脚本:

$ bash mscript.sh 
(92250) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj
(92254) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq

我检查临时文件:

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj
cat: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj: No such file or directory

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq 
something

退出程序时,列表中声明的临时文件subshell会丢失。我理想情况下希望在函数结束时删除它们。要么我必须在离开函数之前专门删除它们,这很容易,而且需要多写一行代码:

mfunc() {
  local tempfile=$(mktemp)
  tmp_add_file $tempfile1
  echo "something" >> $tempfile
  echo "tempfiles: ${tmp_tmp_files[@]}"
  ## Process things...
  rm $tempfile1
}

但我想知道是否有一种优雅的方式可以subshells自动删除它们(在中创建的临时文件),就像我trap退出程序时对 s 所做的那样。

所以我的问题是:可以做到吗? 有什么替代方案吗?

答案1

子 shell 会继承环境或其中的一部分。看起来,当你在子 shell 中执行函数时,你不需要导出变量(比较:在子 shell 中运行函数时不需要导出)。可能有些情况下您需要这样做,export但让我们集中讨论一下您的示例。

你的方法存在缺陷,而且很难维护,因为继承是单向的。每个方法都(mfunc)继承tmp_tmp_files并使用自己的数组副本。它不可能修改tmp_tmp_files主脚本中使用的原始数组。因此,主脚本无法清除所有内容,因为它没有足够的信息。

如果您选择从子 shell 函数中清除,则需要注意区分函数的临时文件和主脚本的临时文件。过早删除后者可能会导致脚本失败。

替代方法:临时目录

  1. 不要创建数组,而是创建一个目录并记住其路径。一开始就做一次,export如果需要的话:

    tempdir=$(mktemp -d mscript.XXXXXXXXXX)
    
  2. 在临时目录内创建每个临时文件,如下所示:

    tempfile=$(mktemp -p "$tempdir")
    
  3. 最后删除整个目录,无论特定文件是由主脚本还是子shell创建,甚至是由某些第三方程序创建的。您可以使用陷阱来执行此步骤。简单地:

    rm -r "$tempdir"
    

相关内容