Cron 作业删除所有超过 7 天的文件:-exec rm -f {} \; vs -删除

Cron 作业删除所有超过 7 天的文件:-exec rm -f {} \; vs -删除

我想运行一个 cron 任务来删除.txt超过 7 天的文件。我有两个命令。第一个命令:

/usr/bin/find /var/www/example.com/wp-content/targetdir -name "*.txt" -type f -mtime +7 -exec rm -f {} \;

第二条命令:

/usr/bin/find /var/www/example.com/wp-content/targetdir -name "*.txt" -type f -mtime +7 -delete

这两个命令都可用于删除.txt7 天以上的文件。我读到第一个命令与race condition.能否详细说明使用第二个命令相对于第一个命令的优点?使用其中一种的优点和缺点是什么?

答案1

我看到提到的比赛是这样的,来自斯特凡·查泽拉斯的评论另一个问题:

请注意,它具有(如果有的话)不存在的-exec rm {} +竞争条件漏洞。-delete所以不要在其他人可写的目录上使用它。一些发现还可以-execdir缓解这些漏洞。

我实际上并没有在那里(*)看到这一点,但我可以看到那里的竞争与如何-exec rm传递文件的完整路径有关,导致在进程中再次遍历树rm

find在遍历树并评估命令行上给出的条件后,rm再次遍历树,并且它不知道给定的条件find,因此现在不检查它们。使用-delete-execdirfind遍历树,进行给定的任何检查,然后删除文件,始终保持目录上的文件描述符打开。

有人可能会介入并在find评估文件或目录的条件和rm运行之间重命名文件或目录。所以,像这样:

  1. 根运行find . -type f -user joe -exec rm -f {} \;
  2. find运行并找到目录./this/,保存用户拥有的一些文件joe
  3. 另一个用户重命名./this并创建具有相同名称的符号链接,指向其他地方
  4. find运行rm -f ./this/hello.txt,现在跟随符号链接。

hello.txt现在可以由任何人拥有,而不仅仅是 user joe,并且自从find作为 启动以来rootrm也是如此,并且它很高兴地删除了符号链接另一端的文件。这是经典检查时间到使用时间 (TOCTTOU) 漏洞

人们可能会举出更糟糕的例子,但这是一个普遍的想法。

使用-delete或,这种情况不会发生,因为打开的-execdir文件描述符仍然指向同一目录,即使该目录被重命名。运行时将其工作目录设置为该目录(系统调用通过文件描述符更改工作目录,同样不进行名称查找),同时类似地使用相对于包含目录的名称进行删除(使用)。find./this-execdirrmfchdir()-deleteunlinkat()

请注意,默认情况下(即没有该-L选项),find不遵循遍历目录树时找到的符号链接。这在这里没有帮助,因为再次rm只是传递给底层系统调用的路径,并且像往常一样遵循符号链接。这确实意味着被替换的目录(./this上面)必须是被符号链接(或另一个目录)替换的实际目录,而不是被另一个符号链接替换的符号链接。

(*)写完这篇文章 20 分钟后,我注意到 Stéphane 的回答(下面链接)确实有描述相同种族问题的 GNU 手册的链接。 (叹。)


-delete暗示-depth和制造的问题-prune与此无关,也不是竞争条件。这在为什么使用 -delete 选项查找会删除我的 /save/ 目录中的文件,而不使用 delete 选项查找却无法找到它们?GNU coreutilsfind似乎已经获得了一条错误消息:

$ find a -name foo -prune -o -name hello.txt -delete
find: The -delete action automatically turns on -depth, but -prune does nothing when -depth is in effect.  If you want to carry on anyway, just explicitly use the -depth option.

另一个区别是-exec rm -f -- {} +仅使用标准工具,而-delete不是标准工具,即使在某种程度上得到普遍支持。例如FreeBSD和GNU支持它,但Busybox不支持。看:查找:“-exec rm {};”与“-delete”——为什么广泛推荐前者?在 superuser.com 上。

相关内容