进程退出后自动销毁的临时文件夹

Bob*_*son 12 file-descriptors tmpfs

我们可以使用临时文件夹之类的临时文件吗

TMP=$(mktemp ... )
exec 3<>$TMP
rm $TMP

cat <&3
Run Code Online (Sandbox Code Playgroud)

这个shell退出后哪个会自动销毁?

Kus*_*nda 14

在临时文件的情况下,您在问题中的示例将创建它,然后将其从目录中取消链接(使其“消失”),并且当脚本关闭文件描述符时(可能在终止时),文件占用的空间可以被系统回收。这是在 C 等语言中处理临时文件的常用方法。

据我所知,不可能以相同的方式打开目录,至少不能以任何方式使目录可用。

在脚本终止时删除临时文件和目录的常用方法是安装清理EXIT陷阱。下面给出的代码示例避免了必须完全处理文件描述符。

tmpdir=$(mktemp -d)
tmpfile=$(mktemp)

trap 'rm -f "$tmpfile"; rm -rf "$tmpdir"' EXIT

# The rest of the script goes here.
Run Code Online (Sandbox Code Playgroud)

或者你可以调用一个清理函数:

cleanup () {
    rm -f "$tmpfile"
    rm -rf "$tmpdir"
}

tmpdir=$(mktemp -d)
tmpfile=$(mktemp)

trap cleanup EXIT

# The rest of the script goes here.
Run Code Online (Sandbox Code Playgroud)

EXIT阱将不会在接收到执行KILL信号(其不能被捕获),这意味着将没有清理然后进行。然而,它会在由于INTorTERM信号终止时执行(如果使用bashor运行ksh,在其他 shell 中,您可能希望EXITtrap命令行之后添加这些信号),或者由于到达脚本末尾或执行一个正常退出时exit称呼。

  • 不仅仅是 shell 不能使用已经取消链接的临时目录——C 程序也不能。问题是未链接的目录中不能有文件。您可以将一个未链接的空目录作为您的工作目录,但任何创建文件的尝试都会出错。 (5认同)
  • 请注意,如果脚本显然调用“exec another-command”,则 EXIT 陷阱也不会执行。 (3认同)
  • 并非所有 shell 在收到 INT/TERM...AFAICT 时都会调用 EXIT 陷阱,只有 ksh 和 bash 会这样做。 (2认同)
  • 另请参阅:[dash 与 ksh 和 bash 中的退出陷阱](//unix.stackexchange.com/q/240723) (2认同)

qub*_*ert 7

您可以 chdir 进入它然后将其删除,前提是您之后不要尝试使用其中的路径:

#! /bin/sh
dir=`mktemp -d`
cd "$dir"
exec 4>file 3<file
rm -fr "$dir"

echo yes >&4    # OK
cat <&3         # OK

cat file        # FAIL
echo yes > file # FAIL
Run Code Online (Sandbox Code Playgroud)

我没有检查过,但是在 C 中使用 openat(2) 和文件系统中不再存在的目录时,这很可能是相同的问题。

如果您是 root 并且在 Linux 上,您可以使用单独的命名空间,并mount -t tmpfs tmpfs /dir在其中使用。

如果您的脚本被迫进入不干净的退出(例如,使用 SIGKILL),则规范答案(在 EXIT 上设置陷阱)不起作用;这可能会留下敏感数据。

更新:

这是一个实现命名空间方法的小实用程序。它应该编译为

cc -Wall -Os -s chtmp.c -o chtmp
Run Code Online (Sandbox Code Playgroud)

并给定CAP_SYS_ADMIN文件功能(以 root 身份)

setcap CAP_SYS_ADMIN+ep chtmp
Run Code Online (Sandbox Code Playgroud)

当(作为普通)用户运行时

./chtmp command args ...
Run Code Online (Sandbox Code Playgroud)

它将取消共享其文件系统命名空间,将 tmpfs 文件系统挂载到/proc/sysvipc, chdir 并command使用给定的参数运行。command不会继承CAP_SYS_ADMIN能力。

该文件系统将无法从另一个不是从 启动的进程访问command,并且当它的子进程command死亡时,它会神奇地消失(包括在其中创建的所有文件),无论这种情况如何发生。请注意,这只是取消共享挂载命名空间——command在同一用户运行的其他进程之间没有硬障碍;他们仍然可以潜行或者通过它的命名空间中ptrace(2)/proc/PID/cwd或通过其他方式。

劫持“无用”/proc/sysvipc当然是愚蠢的,但另一种选择是发送/tmp带有空目录的垃圾邮件,这些目录必须被删除,或者通过分叉和等待使这个小程序大大复杂化。或者,dir可以更改为例如。/mnt/chtmp并在安装时由 root 创建;不要让它由用户配置,也不要将它设置为用户拥有的路径,因为这可能会使您暴露于符号链接陷阱和其他不值得花时间研究的毛茸茸的东西。

chtmp.c

#! /bin/sh
dir=`mktemp -d`
cd "$dir"
exec 4>file 3<file
rm -fr "$dir"

echo yes >&4    # OK
cat <&3         # OK

cat file        # FAIL
echo yes > file # FAIL
Run Code Online (Sandbox Code Playgroud)


Dir*_*man 5

编写一个 shell 函数,当你的脚本完成时它会被执行。在下面的示例中,我将其称为“清理”并设置要在退出级别执行的陷阱,例如:0 1 2 3 6

trap cleanup 0 1 2 3 6

cleanup()
{
  [ -d $TMP ] && rm -rf $TMP
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅帖子。