Ответ 1
Я решил эту проблему, обновив версию PHP до 7.1.12
Это файл 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.
Я решил эту проблему, обновив версию PHP до 7.1.12
Вы запрещаете ошибки в 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
, проблема не является безопасным предположением вообще.
Как указано, отключить отключение или проверить, существует ли файл, отключит эту ошибку.
Разрешение отклоняется, поскольку файл используется другим процессом.
Попробуйте fclose
в файле, перед запуском до unlink
.
Попробуйте это
unlink ('E://temp//test.xml');
Вы можете заметить, что исходный код использует //
для создания, но только /
для удаления.