scp через SFTP: запись удалённых путей, которые действительно разрешаются
Современный scp передаёт через SFTP, поэтому раскрытие тильды и подстановочные знаки ведут себя иначе. Пишите явные пути сервера и осознанно выбирайте протокол.
Команда scp, которая годами работала в скрипте, может отказать на текущем клиенте с ошибкой пути, которая не имеет никакого отношения к туннелю. VPN перенёс байты; клиент запросил у сервера имя, которое сервер не смог разрешить. Текущий OpenSSH scp по умолчанию передаёт через SFTP, а SFTP не выполняет раскрытие в стиле оболочки, как старый протокол. Прослеживание команды от своей учётной записи наружу показывает, где путь действительно интерпретируется.
Начните с учётной записи, затем с каталога, в который она может писать
Двоеточие разделяет два пространства имён, и только левая часть принадлежит машине, на которой вы печатаете. Всё после него разрешает сервер, под учётной записью, с которой вы прошли проверку подлинности, внутри того представления файловой системы, которое есть у этой записи. Подтвердите оба до составления команды, потому что путь, верный для администратора, не обязательно верен для пользователя передачи. Это различие — источник большинства ошибок прав, которые выглядят как сетевые сбои.
Спросите сервер о его собственном представлении: ssh [email protected] pwd и ssh [email protected] ls -ld /srv/archive. Если вторая команда сообщает об отказе в доступе, туннель в порядке, а путь для этой учётной записи непригоден. Исправьте владельца или выберите другое назначение вместо расширения прав, чтобы передача могла продолжиться.
Ограниченная конфигурация SFTP может представлять chroot как корень файловой системы. Внутри этого представления абсолютный путь абсолютен внутри chroot, что не то же самое место, которое администратор видит на хосте.
Называйте обе стороны двоеточия явно
Загрузка должна указывать удалённое имя файла, а не предполагать, что локальное базовое имя будет приемлемо на той стороне.
scp q3-invoice.csv [email protected]:/home/transfer/drop/q3-invoice.csvСкачивание должно указывать локальное назначение по точно той же причине. Два пространства имён независимы, и скрипт, который предполагает их совпадение, ломается в первый раз, когда удалённое дерево использует другую структуру.
scp [email protected]:/srv/archive/2026-q3.csv ./2026-q3.csvИзбегайте ~otheruser в сопровождаемом скрипте. Раскрытие домашнего каталога другой учётной записи было функцией удалённой оболочки, и сервер SFTP может не реализовывать расширение, которое это эмулирует. Запишите абсолютный путь, который учётная запись действительно может открыть, а локальные пути с пробелами заключайте в кавычки вместо копирования слоёв кавычек, написанных для оболочки на сервере.
Знайте, какой протокол на самом деле использует ваш scp
Начиная с OpenSSH 9.0 клиент по умолчанию использует SFTP, а дистрибутивы принимают это поведение или переносят его назад по собственному графику. Строка версии сообщает, что намеревается делать клиент, но сборка поставщика может отличаться от upstream, поэтому проверьте клиент, который вы действительно запускаете: ssh -V.
Два протокола разрешают имена по-разному. Старый SCP просит удалённую оболочку пользователя раскрыть путь, поэтому подстановочные знаки и тильды обрабатывает эта оболочка по своим правилам. SFTP вместо этого выдаёт операции передачи файлов, поэтому подстановочный знак либо раскрывается клиентом, либо не раскрывается вовсе. Оба путешествуют внутри SSH к одной и той же машине, поэтому один хост может вести себя по-разному под двумя клиентами.
scp -v печатает подсистему, которую запрашивает, а строка подсистемы sftp подтверждает, что используется современный путь. scp -O принудительно включает старый протокол там, где он поддерживается и действительно нужен, и приносит с собой собственные правила кавычек. Это не параметр VPN, не способ что-то включить на сервере и не причина ослаблять проверку ключа хоста.
Проверьте путь до того, как скрипт на него положится
Проблема пути проявляется в самый неподходящий момент, в автоматизированной задаче ночью, когда никто не смотрит. Сначала докажите назначение небольшим файлом и точной учётной записью, которую использует задача, и держите эту тестовую команду рядом с определением задачи. Если тесту нужна другая учётная запись или другой каталог, задаче они тоже понадобятся.
Проверьте и сторону сервера. grep -i subsystem /etc/ssh/sshd_config показывает, настроена ли подсистема SFTP, а sftp -b /dev/null [email protected] завершается успешно только тогда, когда эта подсистема отвечает. Хост, который принимает входы SSH, но не имеет подсистемы, терпит неудачу при каждой современной передаче, хотя в тесте входа выглядит совершенно здоровым.
Запишите версию клиента, используемый протокол и абсолютный удалённый путь в заметки задачи. Когда следующее обновление изменит значение по умолчанию, эта заметка станет разницей между пятиминутным исправлением и днём догадок.