终端:列出用户或组具有写权限的所有目录

终端:列出用户或组具有写权限的所有目录

我想列出用户或组具有写权限的所有目录。

我发现ServerFault 上的这个问题但它针对的是 Windows Server,因此我乐观地认为 Linux 社区会为我们找到更好的解决方案。同时,我意识到这个问题存在一个递归问题,如果没有长期运行的脚本,这个问题可能就无法解决。

我知道以下有用的命令:

  • 列出所有组:cut -d : -f 1 /etc/group
  • 列出所有用户:cut -d : -f 1 /etc/passwd
  • 获取用户的主目录:getent passwd user-name| cut -d: -f 6
  • 这个脚本列出每个用户及其组分配
  • 获取文件夹内容的权限和用户/组详细信息:ls -la

但是,当我不知道用户的目的是什么时,最好能列出他们有写入权限的所有目录,然后从那里开始查找。如果没有别的,这是一个非常有用的审计。

如果这有助于理解我的目的,在我们的系统管理员担任新职位后,我继承了(或至少是照看?)几个系统。所以我一直在试图了解这两个系统的演变,比如安装了什么软件,在哪里(呃),各种配置文件放在哪里,现在,创建了哪些不同的组和用户——包括他们被允许写入的目录。通常我可以在 askubuntu 上找到这些有用的终端命令,但没有找到这个,我想继续问。

确切的系统是 Ubuntu 10.04.2,但我们也支持 Ubuntu 12.04.5,因此与版本无关的解决方案是最好的。在此先感谢您的帮助。


[更新:两个快速答案的初步结果]

值得注意的是,我以 root 身份登录,并且/是我的工作目录。此外,它们运行的​​时间相当长。

@Rinzwind 的组合命令在大约 5.5 分钟内得到以下输出..

root@tatooine:/# sudo find -type d \( \( -user ftpgisdata -perm /u=w \) -o \( -group ftpgisdata -perm /g=w \) -o -perm /o=w \)
./tmp
./tmp/.ICE-unix
./tmp/.X11-unix
find: `./proc/6594/task/6594/fd/5': No such file or directory
find: `./proc/6594/task/6594/fdinfo/5': No such file or directory
find: `./proc/6594/fd/5': No such file or directory
find: `./proc/6594/fdinfo/5': No such file or directory
./var/tmp
./var/lib/php5
./var/crash
./var/lock
./home/ftpgisdata
./home/ftpgisdata/.ssh
./home/ftpgisdata/.cache
./home/sitename-i-changed.com/wp-content/profile-pics
./dev/shm

@Oli 修改的命令得到了非常相似的效果,大约需要 5.5 分钟。

root@tatooine:/# sudo find / -type d -print0 | sudo -u ftpgisdata xargs -0 sh -c 'for p; do [ -w "$p" ] && echo "$p"; done' -
/tmp
/tmp/.ICE-unix
/tmp/.X11-unix
find: `/proc/15541': No such file or directory
find: `/proc/15542': No such file or directory
find: `/proc/15543': No such file or directory
find: `/proc/15567': No such file or directory
find: `/proc/15568/task/15568/fd/5': No such file or directory
find: `/proc/15568/task/15568/fdinfo/5': No such file or directory
find: `/proc/15568/fd/5': No such file or directory
find: `/proc/15568/fdinfo/5': No such file or directory
/var/tmp
/var/lib/php5
/var/crash
/var/lock
/home/ftpgisdata
/home/ftpgisdata/.ssh
/home/ftpgisdata/.cache
/home/sitename-i-changed.com/wp-content/profile-pics
/dev/shm

@PeterCordes 的回答也在大约 5.5 分钟内返回了类似的结果。

root@tatooine:~# username_to_check=ftpgisdata base_dir=/   # for example
root@tatooine:~# sudo -u "$username_to_check" find "$base_dir" -type d -writable  2>/dev/null ## GNU find, not POSIX
/tmp
/tmp/.ICE-unix
/tmp/.X11-unix
/proc/7159/task/7159/fd
/proc/7159/fd
/proc/7159/map_files
/var/tmp
/var/lib/php5
/var/crash
/var/lock
/home/ftpgisdata
/home/ftpgisdata/.ssh
/home/ftpgisdata/.cache
/home/sitename-i-changed.com/wp-content/profile-pics
/dev/shm

答案1

如果您不是该用户,那么很难弄清楚该用户可以做什么。您可以测试各种事情(所有者、同一组等),但 ACL 可能适用,挂载中可能没有权限,谁知道呢。这很难。

如果可以的话变成该用户,您可以test -w <path>查看他们是否可以写入。这不如查看 inode 那么快,但使用 是可能的sudo

sudo -u oli test -w <path> && echo "HOORAY"

然后我们可以将其拖放到 的后端find。我们不再只是-exec一遍又一遍地使用 来更改为 oli 用户(参见过去的修订),而是将所有内容导入以 oli 身份运行的 xargs 实例。这样速度要快得多。

sudo find / -type d -print0 | sudo -u oli xargs -0 -I{} sh -c 'test -w "$0" && echo "$0"' {}

一个稍微优化(但视觉上更不美观)的版本涉及通过将路径流传输到少量 bash 子 shell 中来最小化 xargs 执行的子 shell 数量。这对于大型搜索来说无疑更快。

sudo find / -type d -print0 | sudo -u oli xargs -0 sh -c 'for p; do [ -w "$p" ] && echo "$p"; done' -

答案2

在聊天中我们得到了针对用户和群组的以下说明:

sudo find / -type d -user rinzwind -perm /u=w
sudo find / -type d -group rinzwind -perm /g=w
sudo find / -type d -perm /o=w

或者将三者合二为一:

sudo find -type d \( \( -user rinzwind -perm /u=w \) -o \( -group rinzwind -perm /g=w \) -o -perm /o=w \)

如果没有 /,它会搜索当前目录。

在我的系统上,传输 67Gb 数据只花费了不到 2 秒的时间;)

答案3

答案正在制作中,请耐心等待

自我测试

可以使用以下代码测试自己的写权限:

[ -w /home/$USER ] && echo yes # using home directory as example

使用-d标志进行测试,我们可以测试某个东西是否是目录。

知道这一切,find我们可以做到

find /home/ -print0 2> /dev/null | while IFS=""  read -r -d "" file ; do [ -d "$file"  ] &&  [ -w "$file" ]  && echo "$file" is writeable ; done

附注:显然,如果您使用 find 时遇到权限错误,则无法读取该文件,因此没有理由输出这些错误,因此重定向到 dev null。如果我们想找出自己以外的用户的权限,这显然行不通,请注意 - /home 只是一个例子。这样的文件夹确实/var有多个用户共享的文件夹

为他人测试

可以使用stat每个文件find找到并使用 awk 进行过滤

 find /var -type d -exec stat --format '%g %n'  {} \; 2> /dev/null | awk '$1=='1000'{print}' 

这里我过滤的是我自己用户的数字 ID,1000,但它可以是任何用户的 ID。当然,你可以使用选项,使用组名而不是数字 ID。它非常灵活,可以适应你需要的目的

小调整

所以我注意到你提到以 root 身份登录。这是我的命令的输出,其中我统计文件并打印它们的组和文件名,然后使用 AWK 根据适当的组名进行筛选。

$ find /proc -type d -exec stat --format '%G %n'  {} \; 2> /dev/null  | awk '$1=="syslog"{print}'
syslog /proc/560
syslog /proc/560/task
syslog /proc/560/task/560
syslog /proc/560/task/560/net
syslog /proc/560/task/560/attr
syslog /proc/560/task/562
syslog /proc/560/task/562/net
syslog /proc/560/task/562/attr
syslog /proc/560/task/563
syslog /proc/560/task/563/net
syslog /proc/560/task/563/attr
syslog /proc/560/task/564
syslog /proc/560/task/564/net
syslog /proc/560/task/564/attr
syslog /proc/560/net
syslog /proc/560/attr
^C

答案4

如果您有 GNU find,则可以使用-writable测试(请注意拼写,不是writeable)。它使用access(2)系统调用,而不是仅仅通过查看权限来弄清楚事情,因此它可以与 ACL 正确配合使用。(但可能会在具有 ID 映射的 NFS 上中断)。

它还将找到由于属于次要组而可由用户写入的目录。(例如,组/usr/local中的用户可写入的目录admin,或类似的chown root:users /data/share && chmod 2775 /data/share,其中一些帐户是该users组的成员。)

username_to_check=peter base_dir=/   # for example
sudo -u "$username_to_check" find "$base_dir" -type d -writable  2>/dev/null ## GNU find, not POSIX

find当遇到用户无法进入的目录时就会出现错误,因此我们将错误重定向到/dev/null

这会不是查找任何可写入但位于没有执行权限的目录中的目录,因为find以用户身份运行无法遍历上层目录。但是,如果他们拥有的进程在这样的目录中启动,他们将能够使用相对路径对其进行写入。(或者他们掌握了这样的目录的打开文件描述符,他们可以使用openat(2))。 pwd如果他们对完整路径的目录组件之一没有执行权限,则无法工作,因此这不是常见的设置。

这也会错过可执行但不可读的目录内的可写目录。要解决这些限制,可能需要find -type d以 root 身份运行,并find -writable以用户身份使用来检查结果路径。这可能比使用 shell 循环更有效[ -w "$f" ]

POSIXfind(1)选项比 GNU find 要少得多。如果您的脚本必须移植到 POSIX,最简单的方法可能是将其导入到其他检查权限的程序中,例如带有权限的 shell [ -w "$f" ](请参阅建议此操作的其他答案)。

相关内容