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

1

Я вытаскиваю свои волосы, пытаясь написать сценарий непрерывной интеграции с 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 a link. trigger an error.
    if (is_link($dir)) {
        trigger_error("Cannot delete $dir: it a link.", E_ERROR);
        return false;
    }

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

    // it 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 других, которые сейчас похоронены где-то в моем репо.

Что могло быть причиной?

  • 0
    Можете ли вы даже unlink() каталог? Думал, что это было только для файлов.
  • 0
    не забывайте, что вы не можете удалить каталог, если ЛЮБОЙ процесс использует что-либо в / под этим каталогом.
Показать ещё 5 комментариев
Теги:
permission-denied
phing

2 ответа

2

Обе функции 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)

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

  • 0
    ах, я понял, вы правы, префикс / постфикс имеет значение - лучше сделайте это хорошим ответом на оригинальный вопрос, я удалю свою часть вышеупомянутого обсуждения
  • 0
    точно --$x выполняет вычитание FIRST, а затем передает результат в качестве аргумента. $x-- передает исходное значение, затем вычитает, оставляя вычтенное значение в верхней части бесконечного стека рекурсивных вызовов. если рекурсивный вызов когда-либо вернется, то в какой-то момент вы получите attempts = 1 .
1

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

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

  • 0
    Интересно, спасибо - у вас есть еще информация об этом?
  • 0
    Нет, только мой собственный опыт. Насколько я помню, такого не было в XP. Обратите внимание, что если вы видите это постоянно (чаще, чем, скажем, один раз в десять), возможно, есть определенная причина, например, антивирусное программное обеспечение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню