views:

71

answers:

5

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!

A: 

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

stat -c "%a" <filename>

or

stat --printf="%a" <filename>
bedwyr
The stat command doesn't come with all unices. That's why I wrote that I didn't want to use it.
MattBianco
Ah, crap. I missed that note in your post. Sorry :^)
bedwyr
`stat` the command line tool may not, but there is such a system call available with all unix distributions.
Ether
+1  A: 

if you can use find then this looks better:

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

found it here

Aleksey Otrubennikov
Perfect! Too bad it doesn't work on Solaris `find`
MattBianco
+1  A: 

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 -`
Steve Weet
Dennis Williamson
I always place the hyphen last when I use `tr` or write regular expressions.Of course `tr` is more elegant than my initial `sed` for doing the same thing. Thanks, Steve! I'll see if I can use `bc` or `expr` instead of awk.
MattBianco
A: 

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
}
Dennis Williamson
Nice. Thanks! I'm kinda looking for something that don't require any extra installs/files right now, though.
MattBianco
A: 
Norman Ramsey
Lua looks interesting. I will definitely look into it (for other things).
MattBianco