I have a PHP script running which makes symlinks.

To confirm which user it is:

file_put_contents("testFile", "test");
$user = fileowner("testFile");
echo "running as user '" . $user . "'";
var_dump( exec('whoami'));

running like this ...

$ php script.php

runs correct all symlinks are made and output is:

running as user '999'string(5) "admin"

Running through a shell script:

php /path/to/script.php

gives the following output and doesn't work:

PHP Warning: symlink(): Permission denied in /path/to/script.php on line 8 running as user '999'string(5) "admin"

I'm not sure what the difference between the two is, as the users they are running as are identical.

Any suggestions on how to make them both have the correct permissions for symlinking?

cat /proc/version


Linux version 2.6.39 (root@cross-builder) (gcc version 4.6.3 (x86 32-bit toolchain - ASUSTOR Inc.) ) #1 SMP PREEMPT Thu Oct 31 21:27:37 CST 2013

That's the only output I can generate for any sort of release information.

All of the code:

$files = scandir('/volume1/dir1');
$base = "/volume1/";
foreach($files as $file) {
        $f_letter = $file{0};
        $new_path = $base . "ByLetter/" . strtoupper($f_letter) . "/" . $file;
        if(ctype_alpha ($f_letter) && !is_link($new_path)) {
                var_dump($base. "TV/" . $file);
                symlink ($base . "TV/" . $file , $new_path);


gives the same output for the var dumps both methods.

  • AFAIK unlink() deletes file. Is that exactly what you want?
    – dchirikov
    Commented Jun 3, 2014 at 21:42
  • Yes in that case, to check the owner of testfile. Symlink works in the first and fails in the second, yet both are run by the same user
    – exussum
    Commented Jun 3, 2014 at 21:43
  • Ok, see. Then try to check selinux and pwd, may be.
    – dchirikov
    Commented Jun 3, 2014 at 21:50
  • the command setenforce doesnt exist so im fairly sure its not there
    – exussum
    Commented Jun 3, 2014 at 21:57
  • 1
    can you show us the code that actually creates the symlink? I reckon this is probably a lack of absolute paths issue or similar. This is why I always write code paths relative paths to __DIR__. If you are trying to always create the symlink in the cwd, then it will fail whenever executing user is currently in a directory he cannot write to. Commented Jun 23, 2014 at 23:02

3 Answers 3


Try using an absolute path. The code unlink("testFile"); looks for a file at present working directory. The pwd changes according to the current working directory. So use unlink("/path/to/testFile");

  • The script works its supposed to make it in cwd. Its the symlink when which fails at times
    – exussum
    Commented Jun 21, 2014 at 5:58

I took the code you posted, thought it was the beginning of a useful function, tweaked it, and couldn't get it to fail (probably because my user has write access to both paths). I made sure to add lots of checks to let you know if something is going wrong. Let me know if you still get the same issue. Make sure to remember that if you execute the script through the CLI, the script has the permissions as you, however if executed through a webserver, it has the permissions of the webserver user (e.g. www-data)


 * Creates an index of the files in the specified directory, by creating symlinks to them, which
 * are separated into folders having the first letter.
 * WARNING - this will only index files that start with alphabetical characters.
 * @param $directory_to_index - the directory we wish to index.
 * @param $index_location - where to stick the index.
 * @return void
function create_file_index($directory_to_index, $index_location)
    # Don't let the user place the index in the same folder being indexed, otherwise the directory
    # cannot be re-indexed later, otherwise we will be indexing the index.
    if ($directory_to_index == $index_location)
        throw new Exception('Cannot place index in same folder being indexed!');

    # delete the old index if one already exists.
    if (file_exists($index_location))

    if (!mkdir($index_location))
        throw new Exception('Failed to create index directory, check write permissions');

    $files = scandir($directory_to_index);

    foreach ($files as $filename) 
        $first_letter = $filename[0];
        $placement_dir = $index_location . "/" . strtoupper($first_letter);

        if (ctype_alpha($first_letter))
            # create the placement directory if it doesn't exist already

            $new_path = $placement_dir . "/" . $filename;

            if (!is_link($new_path)) 
                symlink($directory_to_index . '/' . $filename, $new_path);

 * Deletes a directory even if it is not already empty. This resolves the issue with
 * trying to use unlink on a non-empty dir.
 * @param String $dir - the path to the directory you wish to delete
 * @return void - changes your filesystem
function deleteNonEmptyDir($dir) 
    if (is_dir($dir)) 
        $objects = scandir($dir);

        foreach ($objects as $object) 
            if ($object != "." && $object != "..") 
                if (filetype($dir . "/" . $object) == "dir")
                    deleteNonEmptyDir($dir . "/" . $object); 
                    unlink($dir . "/" . $object);


create_file_index('/volume1/dir1', '/volume1/dir1/ByLetter');

The PHP function fileowner returns a numeric uid and not a username. The uid 999 probably corresponds to your admin user; you can check this with the command id:

id admin

The output should begin with the uid of that account.

  • It does - also confirmed by the whoami command. both places output the same so its defo the same user. Though 1 place runs successfully and the other fails
    – exussum
    Commented Jun 25, 2014 at 7:05
  • Then your issue is probably unrelated to the user. I'd look into the relative paths as totti suggested. Commented Jun 25, 2014 at 7:56
  • its not a relative pat. That code was there to prove it was running as the same user ..
    – exussum
    Commented Jun 25, 2014 at 8:18

You must log in to answer this question.

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