При настройке стандартного обмена между 1С:Предприятие и сайтом на базе 1С-Битрикс специалисты часто сталкиваются с неприятной ошибкой: Ошибка при вызове конструктора (ЧтениеТекста). В тексте ошибки указывается причина: Ошибка совместного доступа к файлу, и путь к временному файлу в каталоге tmp. Эта проблема особенно актуальна для высоконагруженных систем и серверов, работающих под управлением Linux (Debian, Ubuntu), хотя встречается и на Windows.
В этой статье мы подробно разберем, почему возникает эта ошибка, как проанализировать работу модуля обмена и какие конкретные шаги нужно предпринять в коде и настройках, чтобы стабилизировать интеграцию.
Проанализируем ситуацию. Обмен данными — это итерационный процесс. 1С формирует пакет данных (XML), упаковывает его в ZIP и отправляет на сайт. Сайт обрабатывает пакет и возвращает ответ. Ошибка Ошибка совместного доступа к файлу означает, что один процесс (например, поток записи лога или основной процесс rphost) еще удерживает файл, в то время как другой процесс пытается его прочитать или перезаписать.
Выделим основные факторы, провоцирующие проблему:
Б_ОбменССайтомСервер обращается к текстовому файлу практически на каждом шаге. Если запись в файл не успела завершиться на уровне ОС, следующая попытка обращения вызывает блокировку.Рассмотрим наиболее действенное решение, предложенное опытными разработчиками. Суть заключается в том, чтобы при возникновении ошибки доступа к файлу лога не останавливать весь обмен, а просто изменить имя файла лога и продолжить работу. Нам необходимо внести изменения в процедуру СообщитьПодробно модуля Б_ОбменССайтомСервер.
Разберем по шагам, как модифицировать код:
Попытка
// Пытаемся открыть файл лога для дозаписи
Текст = Новый ЗаписьТекста(ОсновныеПараметры.ИмяФайлаЛога, КодировкаТекста.ANSI, , Истина);
Текст.ЗаписатьСтроку(Строка(ТекущаяДата()) + " -- " + пСобытие);
Текст.Закрыть();
Исключение
// Если файл заблокирован, фиксируем ошибку в Журнале регистрации 1С
ЗаписьЖурналаРегистрации("СобытияОбменаДанныхМодуляБитрикс", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки() + " " + пСобытие);
// Генерируем новое уникальное имя файла, чтобы избежать конфликта
ОсновныеПараметры.ИмяФайлаЛога = СтрЗаменить(ОсновныеПараметры.ИмяФайлаЛога, ".txt", "_.txt");
// Пробуем записать лог в новый файл
Попытка
Текст = Новый ЗаписьТекста(ОсновныеПараметры.ИмяФайлаЛога, КодировкаТекста.ANSI, , Истина);
Текст.ЗаписатьСтроку(Строка(ТекущаяДата()) + " -- " + пСобытие);
Текст.Закрыть();
Исключение
// Если и здесь неудача, просто игнорируем, чтобы не прерывать основной обмен
КонецПопытки;
КонецПопытки;
Этот подход позволяет обойти блокировку, создавая «цепочку» логов (например, log.txt, log_.txt, log__.txt), и гарантирует, что основной процесс загрузки товаров или заказов не прервется из-за второстепенной функции записи отладочной информации.
Если ошибка возникает при чтении файла ответа от сервера (ИмяФайлаОтвета), это часто связано с тем, что HTTP-соединение закрыто, но ОС еще не освободила временный файл. В этом случае мы рекомендуем внедрить цикл ожидания в процедуру ПолучитьОтветСервера.
Проанализируем пример реализации:
// Вместо прямого вызова: ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаОтвета, лКодировка);
// Используем цикл с паузой
МаксПопыток = 5;
Для Итерация = 1 По МаксПопыток Цикл
Попытка
ЧтениеТекста = Новый ЧтениеТекста(ИмяФайлаОтвета, лКодировка);
Прервать; // Успешное чтение, выходим из цикла
Исключение
Если Итерация = МаксПопыток Тогда
// Если все попытки исчерпаны, пробрасываем исключение выше
ВызватьИсключение "Не удалось прочитать файл ответа от сайта после 5 попыток. " + ОписаниеОшибки();
КонецЕсли;
// Небольшая пауза (около 1 секунды) перед следующей попыткой
// В 1С паузу можно реализовать через Предупреждение (но не на сервере!)
// или через фоновое задание/команду ОС.
// Простейший вариант для сервера:
ТекущееВремя = ТекущаяДата();
Пока ТекущаяДата() < ТекущееВремя + 1 Цикл
// Пустой цикл ожидания 1 секунду
КонецЦикла;
КонецПопытки;
КонецЦикла;
Такой подход дает операционной системе время завершить все операции ввода-вывода и снять блокировку с дескриптора файла.
Посмотрим на проблему шире. Иногда изменения кода можно избежать, если правильно настроить окружение и параметры самого модуля Битрикс в 1С.
usr1cv8 есть полные права (777 или rwx) на папку /home/usr1cv8/tmp. Также рекомендуется периодически очищать эту папку от старых файлов *.tmp, так как их накопление (десятки тысяч файлов) замедляет работу файловой системы.umask для пользователя, под которым запущен сервер 1С. Рекомендуется установить umask 0002, чтобы создаваемые файлы были доступны для записи группе.Если проблема сохраняется и кажется неразрешимой на уровне файловой системы, рассмотрим обходной путь: выгрузку в каталог. Вместо прямой передачи данных по протоколу HTTP, настроим 1С на выгрузку файлов в определенную папку на сервере. Затем напишем небольшой скрипт на стороне сайта (или воспользуемся планировщиком), который будет забирать эти файлы.
Преимущества этого метода:
ЧтениеТекста при получении HTTP-ответов.Подведем итог. Ошибка совместного доступа — это чаще всего вопрос таймингов и избыточного логирования. Начнем с отключения детального лога, и если это не поможет, перейдем к модификации кода модуля Б_ОбменССайтомСервер с использованием блоков Попытка...Исключение и уникальных имен файлов. Эти меры позволят сделать ваш обмен с Битриксом стабильным и отказоустойчивым.