При организации автоматического резервного копирования баз данных и рабочих каталогов администраторы часто сталкиваются с ситуацией, когда архиватор 7-Zip завершает работу с кодом возврата 1, а стандартное перенаправление вывода в файл лога через символы > или 2>&1 не срабатывает. Разберем по шагам, почему возникают эти проблемы, как работает перенаправление потоков в операционной системе Windows и как правильно организовать логирование при запуске архиватора из командной строки, скриптов и платформы 1С:Предприятие.
Проанализируем систему кодов завершения (Exit Codes) архиватора 7-Zip. Код 0 означает успешное завершение без ошибок. Код 1 интерпретируется как Предупреждение (Warning / Non-fatal error). На практике это почти всегда означает, что один или несколько файлов во время создания архива оказались заблокированы другими процессами и не были упакованы.
Во время ночной архивации блокировки чаще всего вызывают следующие факторы:
Чтобы архиватор мог считывать файлы, открытые другими программами на запись, используем специальный ключ -ssw (shared write). Также рекомендуется добавлять ключ -y для подавления интерактивных запросов:
7z.exe a "D:\Backups\base.7z" "D:\Data\*" -ssw -y
Рассмотрим распространенную ошибку: попытку передать параметры > log.txt или 2>&1 напрямую в исполняемый файл утилиты из скриптовых языков (AutoIt, VBScript, PowerShell) или метода 1С ЗапуститьПриложение(). В таком сценарии файл лога либо не создается вовсе, либо архиватор выдает синтаксическую ошибку.
Причина кроется в архитектуре Windows: операторы перенаправления потоков (>, >>, |, 2>&1) не являются параметрами программы 7z.exe. Их умеет обрабатывать исключительно командный интерпретатор cmd.exe. Если процесс запускается напрямую, он воспринимает символ > как обычный текстовый аргумент или имя несуществующего файла.
Разберем базовый способ логирования. Чтобы символы перенаправления отработали штатно, команду необходимо оборачивать в вызов cmd.exe /c. Ключ /c указывает интерпретатору выполнить переданную строку и завершить работу.
Посмотрим на пример командной строки с перенаправлением как стандартного вывода (stdout), так и потока ошибок (stderr) в один файл:
cmd.exe /c "7z.exe a D:\Backups\data.7z D:\Source\* -ssw -y > D:\Logs\backup.log 2>&1"
Если требуется не перезаписывать файл журнала, а дописывать новые события в конец существующего, используем оператор >>:
cmd.exe /c "7z.exe a D:\Backups\data.7z D:\Source\* -ssw -y >> D:\Logs\backup.log 2>&1"
В современных версиях 7-Zip предусмотрено семейство параметров -bs, позволяющее явно перенаправлять внутренние потоки сообщений архиватора в стандартные потоки операционной системы:
-bso{0|1|2} — управление стандартным потоком вывода (stdout).-bse{0|1|2} — управление потоком ошибок (stderr).-bsp{0|1|2} — управление отображением прогресса выполнения операции.Значения параметров: 0 — отключить вывод, 1 — направить в stdout, 2 — направить в stderr. Например, перенаправим все сообщения об ошибках в стандартный вывод с помощью ключа -bse1:
cmd.exe /c "7z.exe a D:\Backups\data.7z D:\Source\* -bse1 > D:\Logs\messages.log"
Рассмотрим, как правильно организовать архивацию с сохранением подробного лога непосредственно из программного кода 1С. В платформе доступно несколько механизмов взаимодействия с внешней командной строкой.
Способ А. Использование метода КомандаСистемы()
Метод КомандаСистемы() по умолчанию вызывает командную оболочку операционной системы, поэтому стандартные операторы перенаправления в нем отрабатывают корректно:
СтрокаЗапуска = "cmd.exe /c ""C:\Program Files\7-Zip\7z.exe"" a ""D:\Backup\data.7z"" ""D:\Base1C"" -ssw -y > ""D:\Backup\7z_log.txt"" 2>&1";
КомандаСистемы(СтрокаЗапуска);
Способ Б. Использование метода ЗапуститьПриложение()
Метод ЗапуститьПриложение() позволяет управлять ожиданием завершения процесса и получать код возврата программы. Запуск также выполняем через cmd.exe /c:
СтрокаКоманды = "cmd.exe /c """"""C:\Program Files\7-Zip\7z.exe"""" a """"""D:\Backup\data.7z"""" """"""D:\Base1C"""" -ssw -y > """"""D:\Backup\7z_log.txt"""" 2>&1""";
КодВозврата = 0;
ЗапуститьПриложение(СтрокаКоманды, , Истина, КодВозврата);
Если КодВозврата = 1 Тогда
ЗаписьЖурналаРегистрации("Архивация", УровеньЖурналаРегистрации.Предупреждение, , , "Архив создан с предупреждениями (код 1). Проверьте лог-файл.");
ИначеЕсли КодВозврата > 1 Тогда
ЗаписьЖурналаРегистрации("Архивация", УровеньЖурналаРегистрации.Ошибка, , , "Критическая ошибка архивации. Код возврата: " + Строка(КодВозврата));
КонецЕсли;
Способ В. Чтение потока вывода через WScript.Shell без создания промежуточных файлов
Если необходимо получить лог работы архиватора напрямую в строковую переменную 1С без записи текстового файла на диск, используем COM-объект WScript.Shell и метод Exec():
WshShell = Новый COMОбъект("WScript.Shell");
Команда = """C:\Program Files\7-Zip\7z.exe"" a ""D:\Backup\data.7z"" ""D:\Base1C"" -ssw -y -bse1";
Процесс = WshShell.Exec(Команда);
// Ожидаем завершения и считываем весь стандартный вывод
ТекстЛога = Процесс.StdOut.ReadAll();
КодВозврата = Процесс.ExitCode;
Если КодВозврата <> 0 Тогда
ЗаписьЖурналаРегистрации("Архивация", УровеньЖурналаРегистрации.Ошибка, , , "Результат архивации:" + Символы.ПС + ТекстЛога);
КонецЕсли;
Проанализируем встроенные возможности платформы 1С:Предприятие. Для упаковки данных без вызова сторонних консольных утилит платформа предоставляет встроенный объект ЗаписьZipФайла.
Архив = Новый ЗаписьZipФайла("D:\Backup\base.zip", "ПарольАрхива", "Комментарий к архиву", МетодСжатия.Дефлейт, УровеньСжатия.Максимальный);
Архив.Добавить("D:\Base1C\*", РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталогов.Рекурсивно);
Архив.Записать();
Ограничения встроенного механизма 1С:
-ssw.