如何在可执行文件被杀死时自动删除目录

Joa*_*ela 9 bash files

很多时候,我们运行一个需要写入/读取一些临时文件的可执行文件。我们通常创建一个临时目录,在那里运行可执行文件,并在脚本完成后删除该目录。

即使可执行文件被杀死,我也想删除该目录。我试图将它包装在:

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
/usr/local/bin/my_binary
Run Code Online (Sandbox Code Playgroud)

my_binary死掉时,内核将删除该目录的最后一个进程,因为脚本是持有该目录的最后一个进程inode;但我无法在删除的目录中创建任何文件。

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
touch file.txt
Run Code Online (Sandbox Code Playgroud)

产出 touch: file.txt: No such file or directory

我能想到的最好方法是在进程终止时删除临时目录,捕获最常见的信号,并使用 cron 运行清理进程:

#!/bin/bash
dir=$(mktemp -d /tmp/d.XXXXXX) && cd "$dir" || exit 99
trap 'rm -rf "$dir"' EXIT
/usr/local/bin/my_binary
Run Code Online (Sandbox Code Playgroud)

有没有一些简单的方法来创建一个真正的临时目录,无论发生什么,当当前二进制文件死亡时都会自动删除该目录?

phe*_*mer 4

你的最后一个例子是最安全的。

trap 'rm -rf "$dir"' EXIT
Run Code Online (Sandbox Code Playgroud)

只要 shell 本身仍然有效,就会执行此操作。基本上 SIGKILL 是它唯一不会处理的事情,因为 shell 被强制终止。
(也许SIGSEGV也是如此,没有尝试,但可以捕获)

如果您不将其留给 shell 自行清理,则唯一可能的替代方案是让内核来完成此任务。这通常不是内核功能,但是您可以使用一个技巧,但它有自己的问题:

#!/bin/bash
mkdir /tmp/$$
mount -t tmpfs none /tmp/$$
cd /tmp/$$
umount -l /tmp/$$
rmdir /tmp/$$

do_stuff
Run Code Online (Sandbox Code Playgroud)

基本上,您创建一个 tmpfs 挂载,然后延迟卸载它。一旦脚本完成,它将被删除。
除了过于复杂之外,缺点是如果脚本在卸载之前因任何原因终止,那么您就没有可用的挂载。
这也用到了tmpfs,会消耗内存。但是您可以使该过程更加复杂并使用循环文件系统,并在安装后删除支持它的文件。


trap最终,就简单性和安全性而言,这是最好的,除非您的脚本经常被 SIGKILLed,否则我会坚持使用它。