'unlink', Permission denied error при выполнении функции [exec]

Это файл test1.php:

 <?php    
    set_time_limit(0);
    for($i= 1;$i<5000 ;$i++){

        $comm_sjis = "echo 'test'";
        $result = exec($comm_sjis);

    }
    unset($result);
    echo 'ok';

Это файл test2.php:

<?php

set_time_limit(0);

function write_txt($str)
{
    $filepath = 'E:/temp/test.xml';
    if (($fp = @fopen($filepath, "a")) === false) {
        return;
    }

    if (!flock($fp, LOCK_EX)) {
        @fclose($fp);
        return;
    }

    if (fwrite($fp, $str . "\n") === false) {
        @flock($fp, LOCK_UN);
        @fclose($fp);
        return;
    }

    if (!fflush($fp)) {
        @flock($fp, LOCK_UN);
        @fclose($fp);
        return;
    }

    if (!flock($fp, LOCK_UN)) {
        @fclose($fp);
        return;
    }

    if (!fclose($fp)) {
        return;
    }
}

for($i= 1;$i<100 ;$i++){

    write_txt('test');  
    unlink('E:/temp/test.xml');
}
echo 'ok';

Если я запустил файл test2.php во время работы test1.php, произойдет ошибка:

Предупреждение: unlink (E:/temp/test.xml): разрешение отклонено в C:\xampp\htdocs\test2.php в строке 45

Когда я запускаю test2.php без test1.php, эта ошибка не возникает. Почему unlink дает ошибку Permission denied при выполнении функции?

Я использую XAMPP 3.2 vs php 5.6 с Windows 7.

Ответ 1

Я решил эту проблему, обновив версию PHP до 7.1.12

Ответ 2

Вы запрещаете ошибки в fopen, что означает, что если в любой момент файл не открывается (возможно, из-за ограничения памяти, которое достигается в XAMPP, например), у вас не было бы способа узнать в вашем script (вы можете просмотреть его в своих журналах).

Из Руководство PHP:

bool unlink ( string $filename [, resource $context ] )

Удаляет имя файла. Подобно функции Unink C unlink(). Ошибка ошибки E_WARNING будет возникать при сбое.

unlink удаляет файл. Это означает, что если ваш файл не открывается с помощью fopen, и вы его еще не создали, он, возможно, не существует. Попытка unlink файла, который не существует, приведет к ошибке.

Легким решением было бы также отключить ошибки на unlink.

@unlink('E:/temp/test.xml');

Таким образом, это будет неудачно изящно, если ваша функция не сможет записать файл. Другой вариант - проверить, существует ли файл, прежде чем пытаться отключиться.

$file = 'E:/temp/test.xml';
if (file_exists($file)) {
    error_log(‘could not write file’);
    unlink($file);
}

Моим предпочтительным вариантом в этом случае может быть использование Exceptions. Когда вы не открываете или не открываете файл, введите Exception. Вы можете поймать его, зарегистрировать проблему и разбить цикл, прежде чем пытаться unlink.

Это поможет вам отладить то, что происходит.

Пример:   Тест пространства имен;

class FileException extends \Exception { }
class UnlockFailedException extends FileException { }

function write_txt($str)
{
    $filepath = 'E:/temp/test.xml';
    if (($fp = @fopen($filepath, "a")) === false) {
        throw new FileException('Could not open file');
    }

    if (!flock($fp, LOCK_EX)) {
        @fclose($fp);
        return;
    }

    if (fwrite($fp, $str . "\n") === false) {
        @flock($fp, LOCK_UN);
        @fclose($fp);
        return;
    }

    if (!fflush($fp)) {
        @flock($fp, LOCK_UN);
        @fclose($fp);
        return;
    }

    if (!flock($fp, LOCK_UN)) {
        @fclose($fp);
        throw new UnlockFailedException('Unable to unlock file.');
    }
    /** 
     * This doesn't do anything
     * if (!fclose($fp)) {
     *     return;
     * }
     */
    fclose($fp);
}

Тогда:

$msg = 'ok';
for($i= 1;$i<100 ;$i++){
    try {
        write_txt('test');  
        unlink('E:/temp/test.xml');
    } catch (FileException $e) {
        error_log($e->getMessage());
        $msg = 'errors detected';
    }
}
echo $msg;

Добавляя обработку исключений, вы можете отлаживать это поведение для себя и находить основную причину проблемы.

Несколько заключительных заметок:

Я запускаю Linux, поэтому мне нелегко проверить это поведение на машине Windows 7 XAMPP. Однако я подозреваю, что это связано с тем, что система блокируется из-за ограниченных ресурсов ввода-вывода. Обратите внимание, что в соответствии с руководством Windows помещает блокировку безумной в файл (тогда как в Linux блокировка является рекомендательной). Выполнение flock в массивном цикле и echo в массивном цикле в ограниченной системе ресурсов может привести к сбою ресурсов. Если вы собираетесь запускать что-то подобное в процессе производства, вы не будете сталкиваться с ним так часто, но вам все равно придется его учитывать. Обработка исключений и регистрация ошибок могут гарантировать, что, когда файл не работает, у вас будет достаточно данных для отладки.

Предполагая unlink, проблема не является безопасным предположением вообще.

Как указано, отключить отключение или проверить, существует ли файл, отключит эту ошибку.

Ответ 3

Разрешение отклоняется, поскольку файл используется другим процессом.
Попробуйте fclose в файле, перед запуском до unlink.

Ответ 4

Попробуйте это

 unlink ('E://temp//test.xml');

Вы можете заметить, что исходный код использует // для создания, но только / для удаления.