寻找一种更有效(且可移植)的方法来获取 unix 中的(数字)文件权限

发布于 2024-09-08 16:06:58 字数 973 浏览 10 评论 0原文

简短背景:我需要使用 Zabbix 监视 unix 文件(目录)的权限,以查看它们是否/何时更改。 Zabbix 没有像 vfs.file.mode[xxxx] 这样的内置函数,所以我必须使用数字类型来滚动我自己的 UserParameter。

到目前为止我所做的是使用 ls -l | cut -c 2-10 得到 rwxr-xr-x 部分,然后使用 sed 将字母转换为其“重量”,然后 awksubstr 相加,得到数字 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工具。

大约一周前我“偶然”发现了这个地方,我真的非常喜欢它!令人惊讶的是在一个地方看到这么多的知识、技能和友善! 这是我的第一个问题,所以我很高兴看到是否得到任何答复! :-) 多谢!

Short background: I need to monitor the permissions on a unix file (a directory) with ZABBIX to see if/when they change. ZABBIX doesn't have any built in like vfs.file.mode[xxxx] for this, so I had to roll my own UserParameter, with a numeric type.

What I do so far, is use ls -l | cut -c 2-10 to get the rwxr-xr-xpart, and then use sed to convert letters to their "weight", and awk with substr to sum it up, to get the numeric 755 or whatever value.

This is currently on Solaris, I don't have GNU coreutils stat command, and I want it to be portable and efficient, and only using standard unix tools, that are always available. (IMHO, perl is not always available).

My first attempt (example for the root directory):

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)) ) );}'

As you can see, I don't care about setuid bits or anything other than files, but purist responses are always welcome!

Surely there must be a more elegant solution. Perhaps a standard unix tool that I didn't think of.

I found this place "accidentally" about a week ago, and I really really love it! Amazing to see that much knowledge, skills, and friendliness in one place!
This is my first question, so I'm really excited to see if I get any response! :-)
Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

挖鼻大婶 2024-09-15 16:07:10

ls 的实现各不相同,因此您的 ls 也不是真正可移植的。

我会使用 Lua 来解决这个问题,它可以在任何 ANSI 标准 C 平台上编译,以及 Lua POSIX 库,它应该是开箱即用的任何 POSIX 平台。在那里,您可以直接调用 stat 并编写清晰简单的代码来进行算术运算。关于 Lua 的精彩介绍Lua 编程可免费在线获取(对于Lua 的早期版本)。最后,如果您关心效率,结果将极其高效,部分原因是 Lua 速度很快,但主要是因为您只需分叉一个进程(Lua 解释器)即可完成所有操作。

Implementations of ls vary, so your ls is not really portable either.

I'd solve this problem using Lua, which compiles on any ANSI Standard C platform, together with the Lua POSIX library, which should build out of the box on any POSIX platform. There you can make your stat call directly and write clear simple code to do the arithmetic. An excellent introduction to Lua Programming in Lua is available free online (for the previous version of Lua). Finally, if you care about efficiency, the results will be extremely efficient, partly because Lua is fast, but mostly because you will be able to do everything while forking only one process—the Lua interpreter.

水波映月 2024-09-15 16:07:09

这是啰嗦,但我认为它比你的更易于维护。您可以这样调用它:ls -ld / |切-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
}

This is long-winded, but I think it's more maintainable than yours. You can call it like this: 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
}
嗫嚅 2024-09-15 16:07:08

stat 应该有您要查找的内容。尝试以下其中一项:

stat -c "%a" <filename>

stat --printf="%a" <filename>

stat should have what you're looking for. Try one of these:

stat -c "%a" <filename>

or

stat --printf="%a" <filename>
半世晨晓 2024-09-15 16:07:07

如果您的系统有 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 等。

If your system has bash, and ls -l shows file permissions (rwxrwxrwx), you may accomplish what you were looking for with the following example:

#!/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))

The advantage is that other utilities such as awk or sed are not needed.

紫南 2024-09-15 16:07:06

我不认为这比您自己的版本更优雅/更高效,但我会将其提出,以防任何技术对改进您自己的版本有用。显然,这可以通过脚本更简单/优雅地完成,

基本前提是使用 tr 将 rwx 转换为相关的八进制数字,然后使用 sed 分成 3 个加号组,然后生成 awk 命令字符串whicg传递给 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 -`

I don't believe this is any more elegant/efficient than your own version but I will put it up in case any of the techniques are useful for improving your own. This could obviously be done much more simply/elegantly with a script though

The basic premise is to use tr to translate the rwx to the relevant octal numbers, then use sed to split into groups of 3 add pluses and then generate an awk command string whicg gets passed to awk to add them up.

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 -`
蒲公英的约定 2024-09-15 16:07:05

如果您可以使用 find 那么这看起来会更好:

find FILENAME -prune -printf '%m\n'

找到它 此处

if you can use find then this looks better:

find FILENAME -prune -printf '%m\n'

found it here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文