Почему зависает FTPСоединение в регламентном задании 1С и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интеграций в 1С часто возникает ситуация, когда код подключения к FTP-серверу успешно отрабатывает во внешней обработке в режиме клиента, но при запуске в регламентном или фоновом задании на сервере зависает либо падает с ошибкой инициализации конструктора FTPСоединение. Разберем детально причины такого поведения и способы корректной настройки сетевого обмена на стороне сервера 1С:Предприятия.

1. Включение пассивного режима передачи данных

Самая распространенная причина долгого зависания вызовов конструктора или методов работы с файлами — использование активного режима передачи данных по умолчанию. В активном режиме FTP-сервер пытается самостоятельно открыть входящее TCP-соединение к клиенту. Если сервер 1С находится за NAT, маршрутизатором или межсетевым экраном, входящие пакеты блокируются, и процесс ожидает ответа до истечения системного таймаута TCP.

Для решения проблемы переведем соединение в пассивный режим (Passive Mode), передав значение Истина в 6-й параметр конструктора FTPСоединение. В этом режиме все соединения (как командные, так и для передачи данных) инициируются самой платформой 1С наружу.


// Создание подключения с явным указанием пассивного режима и таймаута
СерверFTP = "ftp.example.com";
ПортFTP   = 21;
Логин     = "ftp_user";
Пароль    = "ftp_password";
Прокси    = Неопределено;
ПассивныйРежим = Истина;
Таймаут   = 30; // таймаут в секундах

Попытка
    Соединение = Новый FTPСоединение(
        СерверFTP,
        ПортFTP,
        Логин,
        Пароль,
        Прокси,
        ПассивныйРежим,
        Таймаут
    );
Исключение
    ЗаписьЖурналаРегистрации(
        "FTP.ОшибкаПодключения",
        УровеньЖурналаРегистрации.Ошибка,,,
        ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())
    );
    Соединение = Неопределено;
КонецПопытки;

2. Настройка уровня защищенного соединения (FTPS)

Начиная с версии платформы 8.3.9, в конструкторе FTPСоединение появились параметры для работы с шифрованием SSL/TLS. По умолчанию платформа может инициировать попытку защищенного подключения. Если FTP-сервер не поддерживает FTPS или мобильный/корпоративный канал связи фильтрует попытки TLS-рукопожатия на 21 порту, вызов конструктора завершается ошибкой или зависает.

Если сервер работает по обычному незащищенному протоколу FTP, отключим шифрование принудительно с помощью перечисления УровеньИспользованияЗащищенногоСоединенияFTP:


// Отключение принудительного защищенного соединения для обычного FTP
УровеньЗащиты = УровеньИспользованияЗащищенногоСоединенияFTP.НеИспользовать;

Соединение = Новый FTPСоединение(
    СерверFTP,
    ПортFTP,
    Логин,
    Пароль,
    Прокси,
    ПассивныйРежим,
    Таймаут,
    УровеньЗащиты
);

Важное различие протоколов: Объект FTPСоединение поддерживает классический протокол FTP и FTPS (FTP поверх SSL/TLS). Протокол SFTP (SSH File Transfer Protocol, работающий через порт 22) данным объектом платформы не поддерживается. Попытка подключиться к SFTP-хосту через FTPСоединение приведет к ошибке протокола или зависанию соединения по таймауту.

3. Особенности выполнения кода в контексте службы сервера 1С

Регламентные и фоновые задания выполняются не под учетной записью пользователя операционной системы, запустившего клиентское приложение, а в контексте системной службы сервера 1С (обычно usr1cv8 в ОС Windows или Linux). Проанализируем различия в сетевом окружении:

  1. Сетевые экраны и фаерволы: Порты, доступные с рабочей станции разработчика (например, через клиентский VPN), могут быть заблокированы для хоста, на котором установлен рабочий сервер 1С. Требуется открыть исходящие подключения к IP-адресу и портам FTP-сервера (порт 21, а также диапазон пассивных портов FTP-сервера).
  2. Параметры системного прокси: У системной службы usr1cv8 нет пользовательских настроек Internet Explorer/браузера. Если в сети используется прокси-сервер или, наоборот, прямое подключение в обход прокси, рекомендуется передавать в конструктор явно инициализированный объект ИнтернетПрокси (например, Новый ИнтернетПрокси(Ложь) при прямом доступе).
  3. Разрешение DNS-имен: Если сервер 1С работает под управлением Linux, проверим корректность работы локального DNS. Если доменное имя резолвится некорректно, можно временно протестировать прямое подключение по IP-адресу хоста.
  4. Профили безопасности кластера 1С: Если в свойствах информационной базы задействованы профили безопасности, любые обращения к внешним интернет-ресурсам на уровне сервера по умолчанию блокируются. Для работы задания администратор 1С должен добавить разрешение на внешний сетевой ресурс (адрес и порт FTP) в используемый профиль безопасности.

4. Комплексный пример обработки файлов на FTP-сервере

Рассмотрим надежный шаблон функции для скачивания файлов из каталога FTP с последующей очисткой удаленного ресурса, корректной обработкой исключений и освобождением сетевых ресурсов:


Процедура ВыполнитьОбменСФТП() Экспорт

    ХостFTP      = "ftp.myserver.ru";
    ПортFTP      = 21;
    ЛогинFTP     = "sync_user";
    ПарольFTP    = "SecretPass123";
    ПутьНаФТП    = "/incoming/";
    ЛокальныйКаталог = "C:\Exchange\In\";

    Попытка
        // Инициализируем соединение: пассивный режим, таймаут 20 секунд, без SSL
        ФТП = Новый FTPСоединение(
            ХостFTP,
            ПортFTP,
            ЛогинFTP,
            ПарольFTP,
            Новый ИнтернетПрокси(Ложь),
            Истина,
            20,
            УровеньИспользованияЗащищенногоСоединенияFTP.НеИспользовать
        );
    Исключение
        ЗаписьЖурналаРегистрации(
            "Обмен FTP",
            УровеньЖурналаРегистрации.Ошибка,,,
            "Не удалось установить связь с FTP: " + ОписаниеОшибки()
        );
        Возврат;
    КонецПопытки;

    Попытка
        // Получаем список файлов по маске
        МассивФайлов = ФТП.НайтиФайлы(ПутьНаФТП, "*.xml");

        Для Каждого ТекущийФайл Из МассивФайлов Цикл
            Если ТекущийФайл.ЭтоФайл() Тогда
                ЛокальныйФайл = ЛокальныйКаталог + ТекущийФайл.Имя;
                
                // Загружаем файл на локальный диск сервера
                ФТП.Получить(ТекущийФайл.ПолноеИмя, ЛокальныйФайл);
                
                // Удаляем обработанный файл с FTP
                ФТП.Удалить(ПутьНаФТП, ТекущийФайл.Имя);
            КонецЕсли;
        КонецЦикла;
    Исключение
        ЗаписьЖурналаРегистрации(
            "Обмен FTP",
            УровеньЖурналаРегистрации.Ошибка,,,
            "Ошибка при обработке файлов: " + ОписаниеОшибки()
        );
    КонецПопытки;

    // Освобождаем объект для немедленного закрытия сокета
    ФТП = Неопределено;

КонецПроцедуры

Рекомендация по освобождению сокетов: Поскольку объект FTPСоединение не содержит явного метода закрытия, сокет удерживается до сборки мусора. Обязательно присваивайте переменной значение Неопределено после завершения цикла обмена, чтобы избежать исчерпания пула свободных исходящих портов операционной системы.

← На главную