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


9

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

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

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

my_binary模具,最后一道工序,内核会删除目录,因为剧本是最后一道工序是持有inode; 但我无法在已删除目录中创建任何文件。

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

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

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

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

有什么简单的方法可以创建一个真正的临时目录,该目录在当前二进制文件消失时会自动删除,无论如何?


1
请注意,cleanup在mktemp完成之前,您可能会执行一个小窗口。您可能需要unset dir在设置陷阱之前。
斯特凡Chazelas

不错,我更新了脚本来处理此问题并处理mktemp中的故障。
Joaquin Cuenca Abela 2014年

我以为退出是强制性的。固定。
Joaquin Cuenca Abela 2014年

您的最后一个示例提到了cron,但与cron无关。最后一个例子也是最安全的方法。唯一无法处理的是SIGKILL。
帕特里克(Patrick)

我没有包括为了使其简洁而运行的cron脚本。在该模式下可以找到超过1小时的dir并对其进行rm处理。我想知道是否有任何解决方案也可以解决sigkill情况,甚至在脚本中间会发生野蛮关机。
Joaquin Cuenca Abela 2014年

Answers:


3

最后一个例子是最安全的方法。

trap 'rm -rf "$dir"' EXIT

只要shell本身仍在运行,这将执行。基本上,SIGKILL是唯一不会处理的事情,因为外壳被强制终止。
(也许SIGSEGV也没有尝试,但可以被抓住)

如果您不让它自己留给外壳清理,那么唯一可行的选择就是让内核来完成。这通常不是内核功能,但是您可以执行一个技巧,但是它有它自己的问题:

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

do_stuff

基本上,您创建一个tmpfs挂载,然后懒地卸载它。一旦脚本完成,它将被删除。
除了过于复杂之外,不利的一面是,如果脚本在卸载之前因任何原因而死亡,那么您将无法进行安装。
这也使用tmpfs,这将消耗内存。但是您可以使过程更加复杂,并使用循环文件系统,并在挂载后删除支持它的文件。


最终trap,就简单性和安全性而言,最好的方法是最好的,除非您的脚本定期得到SIGKILLed,否则我会坚持下去。


疏水阀是放在疏水阀之前mktemp还是之后有关系吗?我想,如果将陷阱放置在之前mktemp,那么即使在陷阱之后和之前接收到退出信号mktemp,所有会发生的情况是rm -rf使用空参数运行命令,但不会执行任何操作。但是,如果陷阱位于之后mktemp,则可能会有一个很小的窗口,可能会留下临时目录。还是我完全脱离基地?
通配符

1

您可以使用等待内置函数来等待后台作业完成:

blah &
wait
rm -rf $DIR

但这等同于blah; rm -rf $DIR,对不对?它的问题是,如果脚本被杀死,它将泄漏$ DIR。
Joaquin Cuenca Abela 2014年

如果子脚本被杀死,则父脚本仍将在清理后继续清理。如果父脚本也被杀死,那么是的,该目录将被丢弃。
马修·克莱恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.