1

I often have the problem that a program - e.g. apache - may not access a certain file or directory.

Solving the problem means to manually check the file and every single directory in the path up to root, and see if the program's user or group may access it. This is tedious.

Which program is able to automatically tell me where the problem is?


I imagine I tell the program the path, user and group - and it shows me where in the tree the problem is. Note that I'm aware of problems like symlinks vs. Apache's -FollowSymLinks directive which cannot be detected that way.

3 Answers 3

4

Assuming you have the root permissions on the system, you can use this

sudo -u USER -g GROUP find ROOTDIR -exec test \! -r {} \; -ls

where USER and GROUP should be replaced with the username and groupname whose access is to be assessed and ROOTDIR is the top directory of the directory tree under which to perform the assessment.

Caveats

Note that sudo must be appropriately configured, meaning that root should be allowed to act as any user as well as any group.

How it works

The command works by executing the test utility for all files and directories under ROOTDIR. The options passed to the utility make it return success (zero) exit code whenever it can not access a given file or directory. This exit code is then use by find to determine whether to print the name of the file or directory (-ls).

Output

Output is the list of files and directories to which USER:GROUP does not have access with extra information about each file and directory similar to the output of ls -l (i.e. with permissions, ownership, modification time etc).

Useful things you can tweak

You can test for different kinds of permissions by replacing -r with a different option, see man test. You can replace -ls with -print if you don't want the extra information about each file and directory, but just their name. Note that if the command finds directories which it cannot traverse it will also complain on stderr. Depending on what you pass to test this may be superficial and can be dropped by redirection.

1

I've put together this simple shell[*] script. Works best when being root:

my_path=/home/me/Documents/a/b/c/file.txt               
while [[ "$my_path" != "/" ]] ; do 
   ls -lLd "$my_path"
   my_path="`dirname \"$my_path\"`" 
done

It still requires some human post-processing, but I don't know any elegant way to check if a specific user has x permission on a directory (it would require either su -c "test -x" or tedious parsing of stat -t).

[*] works in both bash and ksh

0

The command tree will help you with this task.

From man tree:

Tree is a recursive directory listing program that produces a depth indented listing of files.

I built a simple example to demonstrate this use:

$ mkdir {a,b,c}/{1,2,3}
$ ls *
a:
1  2  3

b:
1  2  3

c:
1  2  3
$ 
$ tree
.
|-- a
|   |-- 1
|   |-- 2
|   `-- 3
|-- b
|   |-- 1
|   |-- 2
|   `-- 3
`-- c
    |-- 1
    |-- 2
    `-- 3

12 directories, 0 files
$ sudo chown root b && sudo chmod go-rwx b
$ tree
.
|-- a
|   |-- 1
|   |-- 2
|   `-- 3
|-- b [error opening dir]
`-- c
    |-- 1
    |-- 2
    `-- 3

9 directories, 0 files

You can run tree as the user in question to see where the problem starts. You'd have to fix the found problem and re-run the program until there were no errors to use this as a repair tool, but as you can use tree -if to remove indentation and print full paths, you could hack up a script that runs tree, greps for "error opening dir", grants apache access to that directory, and restarts itself.

2
  • this works for simple trees only, not for /.
    – cweiske
    Jan 3, 2012 at 20:10
  • I don't understand what you mean; how does it not work for /? When I run tree /, I get what looks like reasonable output to me.
    – Handyman5
    Jan 3, 2012 at 23:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .