Как правильно регистрировать только файлы, измененные с помощью PHP shell_exe c? - PullRequest
0 голосов
/ 12 февраля 2020

Я создал скрипт, который копирует измененные файлы с сайта разработки на работающий сайт, который работает безупречно.

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

Я использую shell_exec для запуска rsyn c для копия, а затем пытаюсь обрезать вывод и добавить \n для форматирования.

Вывод выглядит как «отправка инкрементного списка файлов portalMaint. php отправлено 27 659 байт, получено 81 байт 55 48080 байт / с c общий размер 101,582,367 ускорение составляет 3661,95 ".

Вот код, который у меня есть:

$command = "sudo -S rsync -av ".$exclude." ".$source." ".$dest." --delete 2>&1";

    // --- Issue command and check for errors.
    $exErrors = shell_exec($command);

    if (stripos($exErrors, "error:") !== false || stripos($exErrors, "[sudo]")) {
        $error = "Uh-OH, we have a problem! Don't Panic!";
        $errors = $exErrors;

        include("head.php");
        include("template_".$currentPage.".html");
        include("foot.php");
        exit();     
    }else{
        $filesCopied = $exErrors;
        $filesCopied = substr($filesCopied, 0, strrpos($filesCopied, " sent "));
        $filesCopied = preg_replace("/\s+/", "\n", $filesCopied);
    }

Это НЕ работает. $filesCopied в конечном итоге будет пустым.

Если я закомментирую $filesCopied = substr($filesCopied, 0, strrpos($filesCopied, " sent "));, я получу весь вывод в неотформатированном виде.

Что я делаю не так? Мне просто нужны файлы, которые были изменены 1 на строку.

Спасибо.

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Нашел ответ!

Как оказалось, несмотря на то, что вывод оболочки отображался как одна строка, он маскировал разрывы строк. Поэтому, когда дело дошло до форматирования вывода, регулярное выражение не совпадало.

Я отправил выходные данные оболочки в файл, где я увидел, что это разрыв строки.

Итак, я взял переменную вывода оболочки $filesCopied и провел ее через preg_replace() используя \ R в качестве шаблона. Я обнаружил, что здесь: Замените несколько новых строк, табуляции и пробелов

Спасибо @Anggara, поскольку ваш код был лучше моего по форматированию, и это то, что я использую.

Вот мой окончательный код:

    $command = "sudo -S rsync -av ".$exclude." ".$source." ".$dest." --delete 2>&1";

    // --- Issue command and check for errors.
    $exErrors = shell_exec($command);

    if (stripos($exErrors, "error:") !== false || stripos($exErrors, "[sudo]")) {
        $error = "Uh-OH, we have a problem! Don't Panic!";
        $errors = $exErrors;

        include("head.php");
        include("template_".$currentPage.".html");
        include("foot.php");
        exit();     
    }else{
        // -- Strip invisible line breaks
        $filesCopiedRaw = preg_replace('#\R+#', ' ', $exErrors);
        // -- Strip all but files and folders from string and build an array
        preg_match_all('/file list (.*?) sent /', $filesCopiedRaw, $matches);
        $result = $matches[1];
        // -- Convert array to single string
        $filesCopied = "";
        foreach($result as $file) {
            $filesCopied .= $file." ";
        }
        // -- Replace spaces in string with line breaks
        $filesCopied = preg_replace("/\s+/", "\n", $filesCopied);
    }
1 голос
/ 12 февраля 2020

Если ваш неотформатированный вывод имеет тот же шаблон:

sending incremental file list file1.php sent ...
sending incremental file list file2.php sent ...
sending incremental file list file3.php sent ...

, вы можете использовать preg_match_all() для записи имен файлов в массив:

if (preg_match_all('/file list (.*?) sent /', $result, $matches)) {
    $filesCopied = $matches[1];
} else {
    echo 'Pattern does not match';
}
...