我想列出用户或组具有写权限的所有目录。
我发现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" ]
(请参阅建议此操作的其他答案)。