Почему в Windows может попытаться удалить файл дважды?

Я старался изо всех сил пытаться написать скрипт непрерывной интеграции с PHP для машины Windows, на которой я работаю.

Клонировав репозиторий Git, я не смог создать скрипт, который бы все это удалил. (Папка .git и все в них). Я получаю ошибки «Отказано в доступе».

Это казалось прерывистым. Я попытался Phing, но это не удалось, но привело меня к этот билет Phing, так что я не одинок — но это решение с помощью attrib не работает для меня

В конце концов я понял, что это просто две попытки удалить некоторые папки и / или файлы в нем. Итак, мой PHP-код, который наконец заработал, был таким:

<?php
function delTree($dir, $ignore = array()) {

// no need to continue if $dir doesn't exist
if (!file_exists($dir))
return true;

// must not continue if it's a link. trigger an error.
if (is_link($dir)) {
trigger_error("Cannot delete $dir: it's a link.", E_ERROR);
return false;
}

// if it's a file, delete it and return.
if (is_file($dir)) {
return tryUnlink($dir, 2);
}

// it's a directory. so...
// build an array of files/directories within it to delete
$files = array_diff(
scandir($dir), array('.', '..'), $ignore
);

// delete each directory within $dir
foreach ($files as $file) {
delTree("$dir/$file", $ignore);
}

// delete $dir itself
return tryRmdir($dir, 2);
}
function tryUnlink($file, $attempts = 2){
$result = unlink($file);
if (!$result) {
if ($attempts > 1){
return tryUnlink($file, $attempts--);
} else {
trigger_error("Cannot delete file $file", E_ERROR);
return false;
}
}
return true;
}

function tryRmdir($dir, $attempts = 2){
$result = rmdir($dir);
if (!$result) {
if ($attempts > 1){
return tryRmdir($dir, $attempts--);
} else {
trigger_error("Cannot delete directory $dir", E_ERROR);
return false;
}
}
return true;
}

И звать их с $attempts аргумент, установленный на 2, решил все (12 часов спустя).

Я пробовал такие вещи, как chmodв файл 0666закрытие IDE, закрытие SourceTree, любых открытых окон проводника, ношение шляпы из фольги и даже вызов exec() с такими командами, как:

rm -r .git -Force
rmdir .git /s /q

и, вероятно, еще 10, которые сейчас похоронены где-то в моем репо.

Какова могла быть причина?

1

Решение

Обе вы функции tryUnlink() а также tryRmdir() вызовет бесконечный цикл (если он на самом деле не удален). Посмотрите на следующий фрагмент + вывод.

код:

<?php

function foo ($attempts = 2) {
echo "attempts = $attempts\n";
if ($attempts > 1) {
foo ($attempts--);
} else {
echo "returning with \$attempts <= 1\n";
}
}
foo(2);

выход:

attempts = 2
attempts = 2
attempts = 2
[...many many many dupes...]
attempts = 2
attempts = 2
attempts = 2
Segmentation fault (core dumped)

Учитывая, что не сказано, что удаление вступает в силу во втором запуске.

2

Другие решения

Что касается Windows 7 (или, может быть, Vista?), Это редко, но не ненормально, чтобы первая попытка удалить дерево каталогов потерпела неудачу. Я думаю, что это из-за состояния гонки из-за удалений, обрабатываемых файловой системой асинхронно.

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

1

По вопросам рекламы [email protected]