寻找一种更有效(和可移植)的方式在 unix 中获取(数字)文件权限
Posted
技术标签:
【中文标题】寻找一种更有效(和可移植)的方式在 unix 中获取(数字)文件权限【英文标题】:Looking for a more efficient (and portable) way to obtain (numeric) file permissions in unix 【发布时间】:2011-03-12 20:44:27 【问题描述】:简短背景:我需要使用 ZABBIX 监控 unix 文件(目录)的权限,以查看它们是否/何时更改。 ZABBIX 没有像 vfs.file.mode[xxxx] 这样的内置函数,所以我不得不滚动我自己的 UserParameter,使用数字类型。
到目前为止,我所做的是使用ls -l | cut -c 2-10
获取rwxr-xr-x
part,然后使用sed
将字母转换为它们的“重量”,然后使用awk
和substr
进行总结,获取数字 755
或任何值。
这目前在 Solaris 上,我没有 GNU coreutils stat
命令,我希望它具有可移植性和高效性,并且只使用始终可用的标准 unix 工具。 (恕我直言,perl 并不总是可用)。
我的第一次尝试(以根目录为例):
ls -ld / | \
cut -c 2-10 | \
sed -e 's%-%0%g' -e 's%r%4%g' -e 's%w%2%g' -e 's%x%1%g' | \
awk 'print (100 * ((substr($0,1,1)) + (substr($0,2,1)) + (substr($0,3,1))) + \
(10 * ((substr($0,4,1) + (substr($0,5,1)) + (substr($0,6,1)) ))) + \
( (substr($0,7,1)) + (substr($0,8,1)) + (substr($0,9,1)) ) );'
如您所见,我不关心 setuid 位或文件以外的任何内容,但始终欢迎纯粹的回应!
肯定有更优雅的解决方案。也许是我没想到的标准 unix 工具。
大约一周前,我“偶然”发现了这个地方,我真的很喜欢它!在一个地方看到这么多知识、技能和友善,真是太棒了! 这是我的第一个问题,所以我很高兴看到我是否得到任何回应! :-) 非常感谢!
【问题讨论】:
您正在寻找的内容可以通过系统调用轻松获得。没有必要重新发明***,除了“好玩”。 问题是编写我自己的stat(2)
包装器实际上正在重新发明***。我需要一些可以放入配置文件的东西,而无需在被监控的主机上安装额外的程序。
【参考方案1】:
如果你可以使用find
那么这看起来更好:
find FILENAME -prune -printf '%m\n'
找到它here
【讨论】:
【参考方案2】:我不认为这比您自己的版本更优雅/高效,但我会提出它,以防任何技术对改进您自己的技术有用。这显然可以通过脚本更简单/优雅地完成
基本前提是使用 tr 将 rwx 转换为相关的八进制数,然后使用 sed 将 3 个加号分成一组,然后生成一个 awk 命令字符串,将其传递给 awk 以将它们相加。
ls -ld / | \
cut -c2-10 | \
tr 'rwx-t' '42100' | \
sed -E -e 's/(...)(...)(...)/\1 \2 \3/g' \
-e 's/([0-9])([0-9])([0-9])/\1+\2+\3/g' \
-e 's/^(.*)$/BEGIN print \1/g'|\
awk -f -`
【讨论】:
我的tr
抱怨连字符,除非我逃脱了它。您的第一个和第三个g
不是必需的。这是您的 GNU sed 版本,它大大简化了。它可以很容易地转换回-e
形式。 ls -ld / cur -c2-10 | tr 'rwx\-t' '42100' | sed -r 's/(...)/\1 /g;s/([0-9])/\1+0/g;s/.*/BEGIN print &/' | awk -f -
当我使用tr
或编写正则表达式时,我总是将连字符放在最后。当然tr
比我最初的sed
更优雅,因为它做同样的事情。谢谢,史蒂夫!我看看能不能用bc
或expr
代替awk。【参考方案3】:
如果您的系统有bash
,并且ls -l
显示文件权限 (rwxrwxrwx),您可以通过以下示例完成您所寻找的:
#!/bin/sh
[ ! -d $1 ] && echo "Error: "$1" is not a directory" && exit 1
set -- `ls -ld $1`;P=$1:1:9;P=$P//r/4 ;P=$P//w/2 ;P=$P//x/1 ;P=$P//-/0
set -- $P; echo $((($1+$2)+$3))$((($4+$5)+$6))$((($7+$8)+$9))
优点是不需要其他实用程序,例如 awk 或 sed。
【讨论】:
【参考方案4】:stat
应该有你要找的东西。尝试以下方法之一:
stat -c "%a" <filename>
或
stat --printf="%a" <filename>
【讨论】:
并非所有 unice 都带有 stat 命令。这就是为什么我写了我不想使用它。 啊,废话。我错过了你帖子中的那个注释。对不起:^)stat
命令行工具可能没有,但所有 Unix 发行版都有这样的系统调用。【参考方案5】:
这是冗长的,但我认为它比你的更易于维护。你可以这样称呼它:ls -ld / | cut -c 2-10 | ./perm.awk
。
#!/usr/bin/gawk -f
# OR: #!/usr/bin/nawk -f
function conv(num, len, i, val)
# converts binary string to decimal (or octal if fed 3 "bits" at a time)
# call with num as argument, others are local variables
len = length(num)
for(i = len; i > 0; i--)
if (substr(num, i, 1) == 1)
val = val + 2 ^ (len - i)
return val
# main loop
# TODO: handle [sStT]
gsub("[rwx]", 1) # make it look binary
gsub("-", 0)
for(i = 0; i < 3; i++)
perm = perm conv(substr($0, i * 3 + 1, 3)) # convert the "bits" 3 at a time
END
print perm
【讨论】:
不错。谢谢!不过,我现在正在寻找不需要任何额外安装/文件的东西。【参考方案6】:ls
的实现各不相同,因此您的 ls
也不是真正可移植的。
我会使用Lua 解决这个问题,它可以在任何ANSI 标准C 平台上编译,以及Lua POSIX library,它应该在任何POSIX 平台上开箱即用。在那里,您可以直接调用stat
并编写清晰的简单代码来进行算术运算。 Lua Programming in Lua 的精彩介绍可在线免费获得(适用于 Lua 的早期版本)。最后,如果您关心效率,那么结果将非常高效,部分原因是 Lua 速度很快,但主要是因为您将能够在仅派生一个进程(即 Lua 解释器)的同时完成所有工作。 p>
【讨论】:
Lua 看起来很有趣。我一定会调查它(其他事情)。以上是关于寻找一种更有效(和可移植)的方式在 unix 中获取(数字)文件权限的主要内容,如果未能解决你的问题,请参考以下文章