«Обмен не работает» — самая бесполезная формулировка из всех, что приходят в поддержку. Под ней скрывается минимум пять разных ситуаций: 1С не приходила, приходила и получила отказ, прислала пустой файл, прислала полный файл без нужного поля, или всё прошло идеально, а витрина отдаёт кэш.
Каждая из них лечится по-своему, и перебор настроек в админке не приближает ни к одной. Работает другое — чтение источников в жёстко заданном порядке.
Порядок здесь не педантизм. Он экономит часы: восемь из десяти «неразрешимых» проблем закрываются на втором шаге, где выясняется, что спорного поля не было в самой выгрузке, и весь дальнейший разговор про настройки сайта не имеет смысла.
Что такое отладка обмена
Отладка обмена — это восстановление цепочки «1С отправила → сайт принял → сайт разобрал → данные изменились» с определением звена, где цепочка порвалась. Не поиск правильной галочки, а сужение области поиска: каждый источник отвечает ровно на один вопрос и либо снимает подозрение с целого куска системы, либо указывает на него.
Источников четыре, и они читаются в этом порядке.
| № | Источник | Отвечает на вопрос |
|---|---|---|
| 1 | Лог веб-сервера | 1С вообще приходила? |
| 2 | XML в /upload/1c_catalog/ | Что она прислала? |
| 3 | Журнал обмена Битрикса | Что он с этим сделал? |
| 4 | Лог ошибок PHP | Почему упал? |
Источник 1: приходила ли 1С
# Все запросы обмена за сегодня
grep "1c_exchange" /var/log/nginx/access.log | tail -50
# Только коды ответа и режимы — компактная картина цикла
grep "1c_exchange" /var/log/nginx/access.log \
| awk '{print $4, $7, $9}' \
| sed 's/.*mode=\([a-z]*\).*" \([0-9]*\)/\1 \2/' \
| tail -30Что здесь видно сразу:
Запросов нет вообще. Сайт ни при чём. Вопрос к регламентному заданию в 1С или к сети между ними. Разговор с администратором 1С начинается с этой строки, а не с обсуждения настроек Битрикса.
Есть checkauth с кодом 401. Права. Пользователь обмена заблокирован, сменился пароль или его выкинули из группы.
Цепочка обрывается на file. Файл не долез. Смотрите права на запись в /upload/1c_catalog/ и client_max_body_size в nginx — второе особенно вероятно, если каталог недавно вырос.
Десятки одинаковых mode=import подряд. Тот самый бесконечный progress, к которому мы вернёмся отдельно.
Приёмы разбора логов по датам и кодам ответа подробнее разобраны в статье про анализ логов nginx и Apache.
Источник 2: что именно приехало
Здесь закрывается большинство споров. XML-файлы лежат в /upload/1c_catalog/ до следующего обмена, и это единственный достоверный источник того, что было отправлено. Админка показывает результат разбора — то есть уже интерпретацию.
cd /home/site/www/upload/1c_catalog/
ls -la --time-style=full-iso
# Дата формирования и версия схемы — первое, на что смотрим
head -c 400 import.xml
# Есть ли в выгрузке конкретный товар
grep -c "SM-1024" import.xml
# Сколько всего товаров в файле
grep -c "<Товар>" import.xmlДальше — точечная проверка спорного товара. Кириллические теги здесь работают на нас:
# Вырезать блок одного товара по артикулу с контекстом
grep -A 40 "<Артикул>SM-1024</Артикул>" import.xmlДата изменения файла — половина диагноза. Файл вчерашний, а обмен «шёл сегодня ночью» — значит, сегодняшний обмен не дошёл до шага file, и вы смотрите на позавчерашние данные. Эта проверка занимает секунду и регулярно закрывает вопрос целиком.
Не открывайте многогигабайтный import.xml в редакторе. Ни в консольном, ни тем более по SFTP. Каталоги на 100–200 тысяч товаров дают файлы, которые кладут и редактор, и терминал, а на сервере с ними ещё и память съедается. Работайте grep, head, sed -n '1000,1100p' — этого достаточно для любой диагностики.
Источник 3: журнал обмена Битрикса
Журнал включается в настройках модуля торгового каталога, там же указывается путь к файлу. Важная деталь: по умолчанию он выключен. На большинстве проектов его нет, и когда он нужен, включать уже поздно — авария прошла.
Поэтому журнал включают заранее, на этапе настройки обмена, вместе с ротацией:
# /etc/logrotate.d/bitrix-1c-exchange
/home/site/www/upload/1c_exchange.log {
weekly
rotate 8
compress
missingok
notifempty
copytruncate
}Без ротации журнал обмена — это будущий инцидент «на сервере кончилось место», и произойдёт он через несколько месяцев, когда про включённое логирование все забудут.
Источник 4: почему упал
# Ошибки PHP за время обмена
tail -200 /var/log/php-fpm/error.log | grep -iE "fatal|memory|timeout"
# Классика жанра для больших каталогов
grep -i "allowed memory size" /var/log/php-fpm/error.log | tailДва характерных диагноза:
Allowed memory size exhausted. Шаг импорта пытается держать в памяти слишком много. Правильный ответ — уменьшить размер порции в настройках обмена. Поднимать memory_limit можно, но это отодвигает проблему, а не решает: каталог продолжит расти.
Обрыв без записи в лог PHP. Скорее всего, соединение закрыл веб-сервер по своему таймауту, а PHP при этом продолжал работать. Проверяются fastcgi_read_timeout в nginx и max_execution_time в PHP. Как разделять эти два случая, подробно разобрано в статье про диагностику PHP-FPM.
Зависшая сессия: механика бесконечного progress
Это самая непрозрачная неисправность обмена, и она заслуживает отдельного разбора, потому что снаружи выглядит как поломка Битрикса, а формально всё работает правильно.
Напомню устройство шага из разбора протокола обмена: импорт пошаговый, и позиция, на которой он остановился, хранится в сессии. Ответ progress означает «я обработал порцию, приходи ещё за продолжением».
Теперь представим, что 1С не подставляет сессионную куку из ответа checkauth. Что происходит:
Запрос 1 → новая сессия A → прогресс 0 → обработано 500 → progress
Запрос 2 → новая сессия B → прогресс 0 → обработано 500 → progress
Запрос 3 → новая сессия C → прогресс 0 → обработано 500 → progress
...Каждый раз импортируются одни и те же первые 500 товаров. Обмен идёт вечно, база нагружена, данные формально обновляются — и никогда не доходит до конца.
Как убедиться, что дело именно в этом:
# Смотрим, приходит ли кука в запросах импорта.
# В логе её видно, только если формат лога включает $http_cookie;
# если нет — временно добавьте отдельный формат для этого location
grep "mode=import" /var/log/nginx/access.log | tail -5Три причины потери сессии, в порядке частоты:
1С не сохраняет куку. Ошибка настройки на стороне 1С или обмен настроен по устаревшей схеме.
Смена домена или протокола на редиректе. 1С ходит на http://site.ru, сайт редиректит на https://www.site.ru, кука остаётся на другом домене. Проверяется одной командой:
curl -sI "http://site.ru/bitrix/admin/1c_exchange.php?type=catalog&mode=checkauth" | head -3
# Ищем 301/302 — их быть не должно, 1С обязана ходить на конечный адресБалансировщик без липких сессий. Несколько бэкендов, файловое хранилище сессий, каждый запрос попадает на другой сервер. Лечится общим хранилищем сессий или закреплением обмена за одним бэкендом.
Повторный импорт руками
Иногда нужно перезапустить разбор уже лежащего на сайте файла — например, после того как вы поправили сопоставление свойств. Полный цикл обмена ради этого гонять не обязательно.
# 1. Авторизация, сохраняем куки в файл
curl -s -c /tmp/1c.jar -u "exchange1c:password" \
"https://site.ru/bitrix/admin/1c_exchange.php?type=catalog&mode=checkauth"
# 2. Импорт с той же кукой, повторяем до success
for i in $(seq 1 200); do
RESP=$(curl -s -b /tmp/1c.jar -c /tmp/1c.jar \
"https://site.ru/bitrix/admin/1c_exchange.php?type=catalog&mode=import&filename=import.xml")
echo "[$i] $(echo "$RESP" | head -1)"
echo "$RESP" | head -1 | grep -q "^success" && break
echo "$RESP" | head -1 | grep -q "^failure" && break
doneКлючевая деталь — -c вместе с -b: куки не только отправляются, но и обновляются. Без этого вы своими руками воспроизведёте зависшую сессию из предыдущего раздела.
Это настоящий импорт со всеми последствиями. Он изменит цены, остатки и активность элементов ровно так же, как обмен из 1С — включая деактивацию товаров, которых нет в файле, если такая настройка включена. На боевом сайте запускается только после бэкапа базы и с пониманием, что лежит в файле. Отлаживают на копии — той же, на которой проверяют обновления Битрикса.
Симптом → причина → проверка
| Симптом | Вероятная причина | Чем проверить |
|---|---|---|
| Нет запросов в логе | 1С не запускалась или не дошла | grep 1c_exchange access.log |
checkauth возвращает 401 | Права пользователя обмена | curl -u вручную |
Обрыв на mode=file | Права на папку, client_max_body_size | ls -la upload/1c_catalog/ |
Бесконечный progress | Потеряна сессия | Редиректы, куки в запросах |
failure без деталей | Память или права | error.log, вторая строка ответа |
| Обмен успешен, данных нет | Поля нет в XML | grep по артикулу в import.xml |
| Данные в базе, но не на сайте | Кэш каталога | Сброс кэша, политика кэширования |
| Цены не обновились | Тип цены не сопоставлен | Сопоставление в настройках обмена |
| Обмен идёт часами | Обработчик на каждом элементе | Профилирование, события |
| Товары продублировались | Затёрт XML_ID | Сравнение XML_ID с <Ид> в XML |
Итоги
Порядок источников важнее знания настроек. Лог сервера → XML → журнал обмена → лог PHP. Нарушение порядка означает, что вы правите настройки сайта в ситуации, где 1С не приходила вовсе.
XML — единственный достоверный источник того, что прислали. Спор «мы выгрузили, у вас не приехало» разрешается одним grep по артикулу, а не созвоном на сорок минут.
Журнал обмена включайте заранее и с ротацией. Включённый после аварии, он бесполезен; включённый без ротации — сам станет следующей аварией.
Бесконечный progress — это сессия, а не Битрикс. Три причины: 1С не хранит куку, редирект между доменами, балансировщик без липких сессий.
Повторный импорт руками — рабочий инструмент, но с полными последствиями. С -b и -c одновременно, после бэкапа, желательно не на бою.
Наблюдение напоследок. Тяжелее всего диагностируются не падения, а обмены, которые проходят успешно и ничего не меняют. Падение оставляет след в логе, а молчаливое игнорирование несопоставленного свойства — нет. Поэтому первый вопрос при «обмен прошёл, но ничего не изменилось» — не «что сломалось», а «а это поле вообще приезжало». В большинстве случаев ответ отрицательный, и искать на сайте нечего.
Частые вопросы
Где посмотреть лог обмена с 1С в Битриксе?
Журнал обмена включается в настройках модуля торгового каталога, там же задаётся путь к файлу. По умолчанию журнал выключен, поэтому на большинстве проектов его просто нет — включать нужно до того, как понадобится, а не после аварии. Отдельно от него есть лог веб-сервера, который пишется всегда и показывает сами запросы 1С к 1c_exchange.php.
Почему обмен с 1С бесконечно отвечает progress?
Потому что прогресс импорта хранится в сессии, а 1С по какой-то причине её теряет: не сохраняет куку из ответа checkauth, ходит по адресу с другим доменом или через балансировщик, отдающий запросы на разные серверы. Каждый шаг создаёт новую сессию с нулевым прогрессом, поэтому Битрикс честно обрабатывает первую порцию и снова отвечает progress. Внешне это выглядит как зависание, хотя формально всё работает.
Как перезапустить импорт из 1С вручную?
Пройти цепочку curl-запросов к 1c_exchange.php с сохранением куки: checkauth, затем import с именем уже лежащего на сайте файла, затем повторять import до ответа success. Это настоящий импорт, изменяющий данные, поэтому на боевом сайте так делают только осознанно и после бэкапа, а отлаживают на копии.
Обмен прошёл успешно, но данные не изменились. Почему?
Три типичные причины. Первая — нужного поля не было в присланном XML, и это видно за минуту при открытии файла. Вторая — данные обновились в базе, но витрина отдаёт кэш, который никто не сбросил. Третья — сопоставление не настроено: несопоставленный тип цены или свойство игнорируются молча, без единой строчки в логе.
Сколько времени должен занимать обмен с 1С?
Ориентир для каталога в 10 000 товаров — единицы минут на offers.xml и до получаса на полный import.xml. Обмен, который идёт несколько часов, почти всегда упирается не в объём данных, а в обработчик события, выполняющийся на каждом элементе, или в отсутствующий индекс в базе. Это диагностируется профилированием, а не увеличением таймаутов.