我想查找特定用户无法读取的文件。
假设用户名是“user123”,他们在一个名为“user123”的组中。我想找到那些文件,如果它们归 user123 所有,则 u+r 开启;如果文件是 user123 组,则失败,它应该打开 g+r;如果失败,它可以打开 o+r。
由于 GNU find 具有“-可读”,我可以这样做:
sudo -u user123 find /start ! -readable -ls
Run Code Online (Sandbox Code Playgroud)
但是,该进程必须由没有 sudo 访问权限的用户运行。因此我尝试了这个:(它不检查 o+r 但这并不重要)
find /start \( -user user123 ! -perm -u=r \) -o \( -group user123 ! -perm -g=r \) -ls
Run Code Online (Sandbox Code Playgroud)
但它列出了这个文件:
272118 4 -rw------- 1 user123 user123 3243 Jul 3 19:50 /start/blah/blah/file.txt
Run Code Online (Sandbox Code Playgroud)
该文件是/start
user123 拥有的唯一文件,并且g=r
关闭。就好像 find 正在解释-u=r
as -g=r
。
我决定尝试颠倒逻辑并改为测试not ( truth )
:
find /etc/puppet ! \( \( -user puppet -perm -u=r \) -o \( -group puppet -perm -g=r \) -o \( -perm -o=r \) \) -ls
Run Code Online (Sandbox Code Playgroud)
那个有效!
为什么原版find
失败了?这是find
(不太可能)中的错误还是逻辑错误?
更新:我的逻辑错了。正如下面所指出的,因为 ! ( A || B || C ) == ( !A && !B && !C ) 这是两个等效的语句:
find /start ! \( \( -user user123 -perm -u=r \) -o \( -group user123 -perm -g=r \) -o \( ! \( -user user123 -o -group user123 \) -perm -o=r \) \) -ls
find /start ! \( -user user123 -perm -u=r \) ! \( -group user123 -perm -g=r \) ! \( ! \( -user user123 -o -group user123 \) -perm -o=r \) -ls
Run Code Online (Sandbox Code Playgroud)
我的目标是不必两次测试用户/组。我真正需要的是一个更复杂的 if-then-else 结构,这可能只有在有 -xor 运算符时才有可能。我可以用和/或/不构建一个异或,但它会比上面的两个解决方案更复杂。
要检查用户是否可以通过给定路径访问文件,还有很多事情需要考虑:
除非将所有 uid 和 gid 实际切换到用户的 uid 和 gid 并进行检查,否则很难实现与系统相同的逻辑。
使用 zsh,您可以(以 root 身份)执行以下操作:
readable() (
USERNAME=$u
[ -r "$REPLY" ]
)
u=some-user
print -rl -- **/*(DoN^+readable)
Run Code Online (Sandbox Code Playgroud)
或与perl
:
find . -print0 | sudo -u some-user perl -Mfiletest=access -l -0ne '
print unless -r'
Run Code Online (Sandbox Code Playgroud)
也就是说,在这两种情况下,都root
以相应的用户身份下降目录树,但测试文件访问权限。
在某些情况下不会运行find -readable
,some-user
因为它无法通过用户没有访问权限或没有读取权限(但可能有访问权限)的目录。
即使只考虑文件本身的权限和所有权(而不是 ACL 或路径组件......),您也至少需要(这里是 GNU 语法):
u=some-user; g=$(id -G "$u" | sed 's/ / -o -group /g'); IFS=" "
find . ! \( -user "$u" -perm -u=r -o \
! -user "$u" \( -group $g \) -perm -g=r -o \
! -user "$u" ! \( -group $g \) -perm -o=r \)
Run Code Online (Sandbox Code Playgroud)
这个想法是,如果文件归用户所有,则所有其他权限都无关紧要。如果不是,则如果该文件由任何用户组拥有,则“其他”权限无关紧要。
逻辑是错误的。你认为这个文件不应该被列出,因为它归user123
用户所有并且r
设置了用户的位。但是,它被列出是因为它与第二个条件匹配(它归组所有user123
并且组的r
位未设置)。
您的第二个版本之所以有效,是因为de Morgan 定律之一:否定一组语句的逻辑 ORing 在逻辑上等同于 ANDing 对单个语句的否定。换句话说:
! ( A || B || C ) == ( !A && !B && !C )
Run Code Online (Sandbox Code Playgroud)
所以工作find
正在寻找一个文件
user123
并由所述用户读取)并且user123
并且可由所述组读取)并且而第一个find
正在寻找一个文件
user123
且该用户不可读或user123
且该组不可读或(如果您已完成)因此,如您所见,将列出与上述 3 个条件中的任何一个(不一定是全部)匹配的文件。
编辑
顺便说一句(在查看您的个人资料后),我非常喜欢您的 O'Reilly 书 :)