SCP - копируем файлы между серверами

SCP - копируем файлы между серверами

Принцип работы

SCP использует SSH для защищённого соединения и аутентификации. Передача данных происходит внутри зашифрованного SSH-канала.
Начиная с OpenSSH 9.0, scp по умолчанию использует протокол SFTP для непосредственной передачи файлов. Старый SCP-протокол всё ещё доступен и может быть принудительно включён ключом -O
Перед началом копирования между локальным компьютером и удалённым сервером устанавливается зашифрованное SSH-соединение. Для аутентификации можно использовать пароль или ключ SSH

  1. Установка SSH-соединения. scp (сам являясь тонкой оберткой) запускает стандартное SSH-подключение к удалённому хосту - тот же handshake, что при обычном ssh: TCP-соединение, обмен ключами (key exchange), выбор шифра и MAC, аутентификация клиента (по ключу, паролю, agent forwarding и т.д.)
  2. Запрос на удалённой стороне через тот же ssh-канал. Вместо интерактивной shell-сессии SSH-клиент просит сервер запустить то, что будет принимать или отдавать файл. Здесь протоколы расходятся, и это видно в scp -v: по SFTP клиент пишет debug1: Sending subsystem: sftp, то есть запрашивает подсистему sftp; с ключом -O строка другая - debug1: Sending command: scp -f /root/file, то есть на сервере запускается сам scp в режиме источника (-f), а при загрузке на сервер - в режиме приёмника (-t)
  3. Передача данных идёт через тот же зашифрованный SSH-канал (тот самый TCP-поток), никакого отдельного порта для данных не открывается - в отличие от активного FTP, где данные и управление идут по разным соединениям
  4. Завершение - по окончании передачи закрывается ssh-сессия

Синтаксис

scp [опции] источник назначение

Удаленный сервер указывается в формате:
IP_или_DOMAIN:/path/to/file

Например:

  • Скачать файл с сервера: scp root@192.168.1.29:/root/nginx-redis-chart-0.1.0.tgz /share/
    • root@192.168.1.29 - пользователь и IP-адрес удаленного сервера
    • /root/nginx-redis-chart-0.1.0.tgz - файл на сервере, который надо скопировать
    • /share/ - локальная директория, в которую будет скопирован файл
  • Загрузить файл на сервер: scp /home/user/file.txt root@192.168.1.29:/share/
    • /home/user/file.txt - локальный файл, который надо скопировать
    • root@192.168.1.29 - пользователь и IP-адрес удаленного сервера
    • /share/ - директория на сервере, в которую будет скопирован файл

Нюансы

  1. SCP перезаписывает файл без предупреждения
  2. Пробел в пути на удалённой стороне ведёт себя по-разному в зависимости от протокола, и с переходом на SFTP правило упростилось. Замер на OpenSSH 10.0:
    • по умолчанию (SFTP) хватает одного экранирования - кавычек для локального шелла: scp "user@host:/path/with space/file.txt" ./ копирует файл (обратный слеш внутри кавычек тоже принимается, но уже не обязателен)
    • с legacy-протоколом (-O) путь всё ещё уходит удалённому шеллу, поэтому нужны и кавычки, и обратный слеш: scp -O "user@host:/path/with\ space/file.txt" ./. С одними кавычками scp ругается двумя ошибками сразу - /root/with и space.txt: шелл на сервере разорвал путь по пробелу
  3. Поведение wildcard (*, ? и т.д.) зависит от используемого протокола. В современных версиях OpenSSH scp по умолчанию использует SFTP. При использовании legacy SCP-протокола (-O) раскрытие wildcard выполняется удалённым shell, поэтому кавычки и экранирование имеют особое значение
  4. В отличие от rsync, при разрыве соединения на середине передачи большого файла scp начинает копирование с нуля. Нет флага для докачки
  5. Начиная с OpenSSH 9.0, scp по умолчанию использует SFTP-протокол вместо legacy SCP-протокола под капотом. Это меняет поведение в деталях - например, wildcard-раскрытие путей на сервере может работать иначе, и некоторые старые трюки (типа копирования через нестандартные shell-конструкции) перестают работать
    • scp user1@host1:/file user2@host2:/path/
  6. При копировании между двумя удалёнными хостами данные по умолчанию проходят через локальную машину, с которой запущен scp. Не гонять их через себя можно только ключом -R - тогда scp запускается на стороне источника, и источник сам должен попадать на приёмник без пароля

Ключи

-3

Копирование через промежуточный хост - машину, с которой запущена утилита SCP
Полезно, когда host1 и host2 не имеют прямого сетевого доступа друг к другу, но оба доступны с локальной машины
В современных версиях OpenSSH это поведение используется по умолчанию, так что ключ обычно указывать не нужно - он нужен, только если ты одновременно включаешь legacy-протокол ключом -O. Обратный режим - -R

  • scp -3 user1@host1:/path/file.txt user2@host2:/path/

-4

Принудительное использование протокола IPv4
Нужно, если DNS резолвит хост и в IPv4, и в IPv6, а IPv6-соединение до сервера не работает или работает нестабильно

  • scp -4 file.txt user@domain:/tmp/

-6

Принудительное использование протокола IPv6
Нужно, если DNS резолвит хост и в IPv4, и в IPv6, а IPv4-соединение до сервера не работает или работает нестабильно

  • scp -6 file.txt user@domain:/tmp/

-A

Разрешает проброс ssh-agent на удалённую систему. По умолчанию агент не пробрасывается
Нужен, когда с удалённого хоста надо аутентифицироваться дальше - например при копировании между двумя удалёнными хостами ключом -R. У удобства есть цена: проброшенный агент позволяет удалённой машине пользоваться твоими ключами, поэтому на недоверенных хостах его включать не стоит

  • scp -A -R user1@host1:/file user2@host2:/path/

-B

Batch mode - отключает запрос пароля/passphrase, работает в неинтерактивном режиме. Если аутентификация не пройдёт автоматически (по ключу), scp просто завершится с ошибкой, а не будет ждать ввода
Используется в скриптах и cron-задачах, где никто не сидит рядом с терминалом, чтобы ввести пароль

  • scp -B -i ~/.ssh/id_rsa file.txt user@host:/tmp/

-C

Включить сжатие данных (передаёт -C в ssh, тот же алгоритм compression, что и в обычном ssh)
Ускоряет передачу на медленных каналах для сжимаемых данных (текст, логи). Для уже сжатых файлов (архивы, видео, изображения) эффекта почти нет, а CPU тратится зря

  • scp -C bigfile.tar user@host:/backup/

-c [шифр]

Выбор шифра для соединения (передаётся в ssh как -c)
Список доступных шифров можно посмотреть через ssh -Q cipher. Раньше это имело смысл для баланса скорость/безопасность на слабом железе, сейчас редко нужно - современные шифры типа chacha20-poly1305 или aes128-gcm быстрые сами по себе

  • scp -c aes128-gcm@openssh.com file.txt user@host:/tmp/

-F [конфиг-файл SSH]

Указывает альтернативный конфиг-файл ssh вместо ~/.ssh/config
Удобно, когда нужны разные наборы настроек (разные Jump-хосты, ключи, порты) для разных контекстов - например, рабочий и личный

  • scp -F ~/.ssh/config_work file.txt user@host:/tmp/

-i [приватный SSH-ключ]

Путь к приватному ключу для аутентификации
Если не указать, ssh использует ключи по умолчанию (id_rsa, id_ed25519 и т.д.) из ~/.ssh/. Нужен, когда ключ лежит в нестандартном месте или используется отдельный ключ под конкретный сервер

  • scp -i ~/.ssh/id_ed25519 file.txt user@host:/tmp/

-J [адрес прокси-сервера]

Jump host - прокси-сервер, через который устанавливается ssh-туннель до конечного хоста (аналог ProxyJump)
Классический сценарий: внутренний сервер недоступен из интернета напрямую, но доступен через bastion/jump-хост. В отличие от -3, здесь данные всё равно идут "сквозь" jump-хост как через туннель, а не копируются им как промежуточным участником

  • scp -J jumpuser@bastion.example.com file.txt user@internal-host:/tmp/

-l [скорость в килобитах]

Ограничение скорости передачи в Kbit/s
Здесь 800 Kbit/s ≈ 100 KB/s. Полезно, чтобы не забить весь канал при копировании большого файла на продакшн-сервере, который сейчас обслуживает живой трафик

  • scp -l 800 bigfile.iso user@host:/tmp/

-O

Принудительно использовать legacy SCP-протокол вместо SFTP
Нужен для серверов, где нет SFTP-подсистемы, а также ради совместимости с раскрытием wildcard и путей с ~ на старых серверах. Заодно это удобный маркер версии: в man-странице OpenSSH 8.9 у -O написано «This mode is the default», а в 10.0 - уже «legacy SCP protocol». Обратный ключ -s (принудительный SFTP) в man 10.0 уже не описан: он просто не нужен, хотя всё ещё принимается

  • scp -O user@host:'/var/log/*.log' ./

-o [SSH-параметр]

Передать произвольную опцию ssh в формате key=value (как в ssh_config)

  • scp -o StrictHostKeyChecking=no -o ConnectTimeout=5 file.txt user@host:/tmp/

-P [порт]

Порт SSH-сервера на удалённой машине (по умолчанию 22)

  • scp -P 2222 file.txt user@host:/tmp/

-p

Сохраняет modification time, access time и права доступа (permissions) файла при копировании
Без -p файл получит текущее время, а права возьмутся от источника, но будут урезаны umask получателя - это не то же самое, что «права по umask». Замер на OpenSSH 10.0: файл с правами 741 приезжает как 741 при umask 022 и как 700 при umask 077; с -p в обоих случаях остаётся 741, и сохраняется исходное время. Legacy-протокол (-O) ведёт себя так же
С -p сохранятся оригинальные метаданные - важно для бэкапов, деплоя скриптов, где права/время имеют значение

  • scp -p script.sh user@host:/usr/local/bin/

-q

Quiet mode - отключает индикатор прогресса и большинство сообщений (кроме ошибок)
Удобно в скриптах, где прогресс-бар только мусорит вывод/логи

  • scp -q file.txt user@host:/tmp/

-R

Копирование между двумя удалёнными хостами силами самого источника: scp запускается на host1, и host1 сам подключается к host2
В отличие от -3, данные не идут через локальную машину. Условие: scp на host1 должен попадать на host2 без пароля - ключом на месте или через проброшенный агент (-A)

  • scp -R user1@host1:/file user2@host2:/path/

-r

Рекурсивное копирование директорий
Без -r scp откажется копировать директорию и выдаст ошибку. Копирует всё содержимое рекурсивно, включая поддиректории

  • scp -r ./project user@host:/var/www/

-S [программа]

Программа для установки шифрованного соединения вместо стандартного ssh (должна понимать те же флаги, что и ssh)
Редко используется на практике - разве что для отладки через обёртку-скрипт, которая логирует вызовы, или для использования альтернативной ssh-реализации

  • scp -S /usr/bin/ssh file.txt user@host:/tmp/

-T

Отключает проверку совпадения имён файлов между тем, что запросил клиент, и тем, что вернул сервер (strict filename checking)
Нужен в редких случаях - например, когда путь на сервере содержит спецсимволы или wildcard-раскрытие на удалённой стороне даёт результат, который стандартная проверка ошибочно блокирует. Ослабляет защиту

  • scp -T user@host:/some/weird/*.log ./

-v

Verbose - подробный вывод отладочной информации о процессе соединения и передачи (согласование ssh, аутентификация, шифр и т.д.)
Покажет, где именно происходит зависание или отказ (DNS, TCP, аутентификация, permission denied на удалённой стороне и т.п.)

  • scp -v file.txt user@host:/tmp/

-X [SFTP-параметр]

Настройка поведения SFTP, появилась вместе с переходом на этот протокол. Параметров два: nrequests - сколько запросов чтения/записи держать в полёте одновременно (по умолчанию 64), и buffer - размер буфера одной операции (по умолчанию 32 КБ)
Это ручка для каналов с большой задержкой: на «длинной толстой трубе» передача упирается не в полосу, а в число запросов в полёте, и поднимать nrequests с buffer имеет смысл там, где сжатие и выбор шифра уже ничего не дают

  • scp -X nrequests=128 -X buffer=262144 bigfile.iso user@host:/tmp/

Тренажёр: собери команду

Ключи запоминаются не чтением, а набором. Ниже - задания прямо на этой
странице: условие словами, а ты пишешь команду. Проверяется не текст, а разбор -
ключи можно ставить в любом порядке, писать слитно (-rp) и цеплять значение к
ключу (-P2222). Задания каждый раз собираются заново с другими путями и
хостами, так что запомнить строку не выйдет.

#linux#гайд

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.