Если на сервере нет команды scp, не ищите отдельный пакет — его нет. scp, sftp и ssh входят в клиент OpenSSH. В Debian и Ubuntu это пакет openssh-client, в AlmaLinux и Rocky Linux — openssh-clients. На минимальной установке или в контейнере его часто нет, отсюда и ошибка scp: command not found.
Вторая новость: протокол SCP устарел. Начиная с OpenSSH 9.0 команда scp по умолчанию работает поверх SFTP, а старый протокол включается ключом -O. Для пользователя синтаксис почти не изменился, но на старых или урезанных серверах это иногда ломает копирование.
Короткая рекомендация: один-два файла — scp; интерактивная работа с файлами на удалённой машине — sftp; каталоги, большие объёмы и всё, что может оборваться, — rsync -avz --partial. Все три работают через SSH и используют одни и те же ключи и порт.
Установка: если scp, sftp или rsync нет
| Система | Клиент (scp, sftp, ssh) | Сервер SFTP | rsync |
|---|---|---|---|
| Debian 12 / 13, Ubuntu 24.04 | apt install openssh-client | openssh-server + openssh-sftp-server | apt install rsync |
| AlmaLinux / Rocky 9 и 10 | dnf install openssh-clients | openssh-server (sftp-server внутри) | dnf install rsync |
| FreeBSD 14.x | OpenSSH в базовой системе | в базовой системе | pkg install rsync |
Версии OpenSSH на момент написания: Debian 12 — 9.2, Debian 13 — 10.0, Ubuntu 24.04 — 9.6, AlmaLinux 9 и 10 — 9.9. Свою версию смотрите командой ssh -V.
Есть важная деталь, на которой спотыкались ещё на CentOS: для старого протокола SCP нужен scp на обеих машинах. Удалённый сервер запускает у себя scp -t или scp -f. Если там минимальная система без клиента OpenSSH, вы получите на своей машине ошибку вроде bash: scp: command not found, хотя у вас scp есть. В режиме SFTP на удалённой стороне нужен не scp, а подсистема sftp-server.
rsync тоже должен быть установлен с двух сторон. Иначе будет rsync: command not found и rsync error: remote command not found (code 127).
scp: копирование одной командой
Базовый синтаксис
# файл на удалённый сервер
scp backup.tar.gz user@server.example.ru:/srv/backup/
# файл с сервера к себе
scp user@server.example.ru:/var/log/nginx/error.log ./
# каталог целиком
scp -r /var/www/site user@server.example.ru:/var/www/
# сохранить время изменения и права
scp -p config.yml user@server.example.ru:~/
Основные ключи:
-P 2222— порт SSH. Заглавная P, в отличие отssh -p.-r— рекурсивно, для каталогов.-p— сохранить время изменения, время доступа и права.-i ~/.ssh/id_ed25519— конкретный ключ.-C— сжатие. Полезно для текста на медленном канале, бесполезно для архивов и видео.-l 8192— ограничение скорости в килобитах в секунду (8192 — примерно 1 МБ/с).-J jump@bastion.example.ru— через промежуточный хост.-3— копирование между двумя удалёнными серверами через вашу машину.-O— использовать старый протокол SCP вместо SFTP.
Почему SCP заменили на SFTP
Старый протокол SCP — это по сути удалённый запуск scp через shell. Имена файлов разбирает shell на удалённой стороне. Отсюда вечные проблемы с пробелами и спецсимволами, двойное экранирование и уязвимости. Например, в 2019 году нашли, что злонамеренный сервер мог подсунуть клиенту лишние файлы (CVE-2019-6111). Разработчики OpenSSH прямо называют протокол устаревшим и негибким.
В OpenSSH 9.0 scp переключили на SFTP (см. примечания к выпуску OpenSSH 9.0). Команды остались прежними, но изменилось поведение:
- имена с пробелами больше не нужно экранировать дважды;
- шаблоны
*в удалённом пути разбирает сам SFTP, а не shell; ~в удалённом пути работает, если сервер поддерживает расширениеexpand-path@openssh.com(OpenSSH 8.9 и новее);- на удалённой стороне должна быть включена подсистема SFTP.
Когда нужен -O
Старый протокол через -O нужен в трёх случаях:
- на удалённом сервере SFTP отключён или не установлен (часто — встроенные системы, роутеры, старые NAS);
- сервер — не OpenSSH, а, например, Dropbear без SFTP;
- скрипт полагается на разбор удалённого пути shell-ом, например
scp server:'/var/log/*.{1,2}' ..
scp -O firmware.bin root@192.168.1.1:/tmp/
Если новый scp падает с ошибкой вроде scp: Connection closed или subsystem request failed on channel 0, а scp -O работает, — на сервере нет SFTP. Лучше включить его, чем навсегда переходить на -O (см. ниже).
sftp: интерактивная работа с файлами
sftp — это «FTP поверх SSH». Удобен, когда нужно посмотреть, что лежит на сервере, и забрать часть файлов. Отдельный FTP-сервер для этого не нужен.
sftp -P 2222 user@server.example.ru
sftp> ls -l /var/www
sftp> cd /var/www/site
sftp> get -r uploads
sftp> lcd /tmp
sftp> put dump.sql.gz
sftp> reget big.iso
sftp> bye
Полезные команды: get / put (с -r для каталогов), reget / reput — докачка оборванного файла, lcd и lls — работа с локальным каталогом, df -h — место на удалённой стороне.
Для скриптов есть пакетный режим. Команды берутся из файла, при ошибке выполнение останавливается:
cat > batch.txt <<'EOF'
cd /srv/upload
put report.csv
EOF
sftp -b batch.txt user@server.example.ru
Для пакетного режима нужна авторизация по ключу: пароль из файла sftp не прочитает.
Как включить SFTP на сервере
В /etc/ssh/sshd_config должна быть строка Subsystem sftp. Пути отличаются:
# Debian / Ubuntu
Subsystem sftp /usr/lib/openssh/sftp-server
# AlmaLinux / Rocky
Subsystem sftp /usr/libexec/openssh/sftp-server
# или встроенный в sshd вариант, на любой системе
Subsystem sftp internal-sftp
В Debian и Ubuntu сам sftp-server вынесен в пакет openssh-sftp-server. Обычно он ставится вместе с openssh-server как рекомендованный, но при установке с --no-install-recommends его может не быть. После правки проверьте конфигурацию и перечитайте её:
sshd -t && systemctl reload ssh # Debian / Ubuntu
sshd -t && systemctl reload sshd # AlmaLinux / Rocky
Не закрывайте текущую сессию SSH, пока не проверите вход в новом окне.
rsync: каталоги, большие объёмы, докачка
rsync сравнивает файлы на двух сторонах и передаёт только изменения. Повторный запуск после обрыва докачивает недостающее, а не начинает заново. Для переноса сайтов, бэкапов и образов дисков это основной инструмент.
Базовая команда
rsync -avz --partial /var/www/site/ user@server.example.ru:/var/www/site/
-a— архивный режим: рекурсивно, с правами, временем, симлинками, владельцем и группой (владелец сохраняется, если на приёмнике вы root);-v— показывать файлы;-z— сжатие при передаче;--partial— не удалять недокачанный файл при обрыве, чтобы продолжить с того же места;-P— сокращение для--partial --progress.
Слэш в конце пути
Самая частая ошибка с rsync. /var/www/site/ со слэшем значит «содержимое каталога». /var/www/site без слэша — «сам каталог». Команда rsync -a site user@host:/var/www/site/ создаст на приёмнике /var/www/site/site.
Нестандартный порт и ключ
rsync -avz -P -e "ssh -p 2222 -i ~/.ssh/id_ed25519" ./backup/ user@server.example.ru:/srv/backup/
Зеркало с удалением лишнего
# сначала пробный запуск: покажет, что будет удалено
rsync -avn --delete /var/www/site/ user@server.example.ru:/var/www/site/
# затем реальный
rsync -av --delete /var/www/site/ user@server.example.ru:/var/www/site/
--delete удаляет на приёмнике файлы, которых нет в источнике. Перепутанные местами источник и приёмник с этим ключом — классический способ потерять данные. Всегда запускайте сначала с -n (--dry-run).
Другие полезные ключи
--exclude='cache/',--exclude-from=файл— исключения;--bwlimit=5000— ограничение скорости, по умолчанию в КиБ/с (здесь около 5 МБ/с);--info=progress2— общий прогресс по всей передаче вместо прогресса по каждому файлу;-H,-A,-X— жёсткие ссылки, ACL и расширенные атрибуты (нужны для полного переноса системы);--append-verify— дописать оборванный большой файл и проверить контрольную сумму целиком.
Пример полного переноса сайта на WordPress с базой данных — в статье о переносе WordPress из командной строки.
Ключи SSH: чтобы не вводить пароль
Для регулярного копирования и скриптов нужна авторизация по ключу. Пароли в скриптах и утилиты вроде sshpass — плохая идея: пароль оказывается в истории команд, в списке процессов и в файлах.
# создать ключ (ed25519 — короткий и быстрый)
ssh-keygen -t ed25519 -C "backup@web1"
# скопировать публичный ключ на сервер
ssh-copy-id -p 2222 user@server.example.ru
# проверить
ssh -p 2222 user@server.example.ru 'echo ok'
Чтобы не писать порт и пользователя каждый раз, добавьте хост в ~/.ssh/config. Эти настройки подхватят ssh, scp, sftp и rsync:
Host web1
HostName server.example.ru
Port 2222
User deploy
IdentityFile ~/.ssh/id_ed25519
scp dump.sql.gz web1:/tmp/
rsync -avP ./site/ web1:/var/www/site/
sftp web1
Для ключа резервного копирования на сервере можно ограничить действия. Для rsync в пакете есть скрипт rrsync: в authorized_keys перед ключом пишется command="rrsync /srv/backup",restrict, и по этому ключу можно только обмениваться файлами с указанным каталогом. Путь к скрипту и имя пакета отличаются по дистрибутивам — проверьте man rrsync.
Скорость: что реально помогает
Копирование по SSH упирается в одно из трёх: канал, диск или процессор (шифрование). Сначала поймите, что именно.
- Много мелких файлов. Задержка на каждом файле съедает всё время. Упакуйте поток в tar:
tar -C /var/www -czf - site | ssh web1 'tar -C /var/www -xzf -' - Быстрая локальная сеть. Сжатие (
-z,-C) замедляет: процессор не успевает. Уберите его. Для rsync в сети 1–10 Гбит/с при первом копировании помогает-W(передавать файлы целиком, без поиска различий). - Уже сжатые данные (архивы, видео, образы qcow2 со сжатием).
-zне даёт выигрыша. В rsync 3.2 и новее можно указать--compress-choice=zstd, но для таких данных проще отключить сжатие. - Слабый процессор. На процессорах с AES-NI быстрее всего AES-GCM:
scp -c aes128-gcm@openssh.com. На ARM без аппаратного AES обычно быстрееchacha20-poly1305@openssh.com— шифр по умолчанию. - Медленный канал и общий сервер. Ограничьте скорость, чтобы не положить сайт:
scp -lилиrsync --bwlimit.
Старые советы вроде «используйте шифр arcfour» не работают: слабые шифры давно удалены из OpenSSH, и ssh просто откажется подключаться.
Для больших образов виртуальных машин сначала уменьшите сам файл (сжатие, удаление пустых блоков) — об этом в статье про образы дисков QEMU-KVM, Xen и VMDK. Разреженные файлы rsync копирует с ключом -S (--sparse), иначе на приёмнике они займут полный объём.
Готовые примеры
Дамп базы сразу на другой сервер, без временного файла
mysqldump --single-transaction site_db | gzip | ssh web2 'cat > /srv/backup/site_db.sql.gz'
Место на исходном сервере не расходуется. Пароль к базе держите в ~/.my.cnf с правами 600, а не в командной строке.
Забрать логи за прошлые дни с сервера
rsync -av --include='*.gz' --exclude='*' web1:/var/log/nginx/ ./logs/web1/
Порядок правил важен: сначала включение нужных файлов, затем исключение всех остальных.
Большой файл по нестабильному каналу
rsync -av --partial --append-verify --timeout=60 web1:/srv/images/vm.qcow2 /backup/
Если связь оборвалась, повторите ту же команду: rsync допишет файл и проверит его целиком. Для надёжности её можно завернуть в цикл until rsync ...; do sleep 30; done.
Ежедневная копия каталога по расписанию
# /etc/cron.d/site-backup
15 3 * * * backup rsync -a --delete /var/www/site/ backup-host:/srv/backup/site/ >> /var/log/site-backup.log 2>&1
Перед тем как ставить такую задачу в cron, один раз выполните её вручную с -n и проверьте вывод. Учтите: --delete делает зеркало, а не историю версий. Если файл удалили на сайте, к утру его не будет и в копии.
Сравнение: что выбрать
| Задача | scp | sftp | rsync |
|---|---|---|---|
| Скопировать один-два файла | Лучший выбор | Можно | Можно |
| Посмотреть и выбрать файлы на сервере | Нет | Лучший выбор | Нет |
| Большой каталог, повторная синхронизация | Копирует всё заново | Неудобно | Лучший выбор |
| Докачка после обрыва | Нет | reget, reput | --partial, --append-verify |
| Нужно на удалённой стороне | SFTP-сервер (или scp для -O) | SFTP-сервер | rsync |
| Работает с роутерами и встроенными системами | Часто только с -O | Если есть SFTP | Редко |
Симптомы и решения
| Симптом | Причина | Решение |
|---|---|---|
scp: command not found на своей машине | Не установлен клиент OpenSSH | apt install openssh-client или dnf install openssh-clients |
bash: scp: command not found при scp -O | На удалённом сервере нет клиента OpenSSH | Установить его на сервере или работать без -O |
subsystem request failed, Connection closed | На сервере отключён SFTP | Включить Subsystem sftp или временно scp -O |
rsync: command not found, код 127 | rsync не установлен на удалённой стороне | Установить rsync на сервере |
ssh: connect to host ... port 22: Connection refused | SSH на другом порту | scp -P, sftp -P, rsync -e "ssh -p ..." или ~/.ssh/config |
Permission denied (publickey) | Ключ не добавлен или неверные права на ~/.ssh | ssh-copy-id; права 700 на ~/.ssh, 600 на authorized_keys |
| Мусор в выводе, «protocol version mismatch» у rsync или sftp | Скрипт входа (.bashrc) что-то печатает при неинтерактивном входе | Убрать вывод из .bashrc или обернуть проверкой на интерактивность |
| Каталог оказался внутри одноимённого каталога | Нет слэша в конце пути источника rsync | Писать src/, если нужно содержимое |
Частые вопросы
scp удалят из OpenSSH?
Команда scp остаётся, меняется только протокол под ней. Старый протокол SCP пока доступен через -O, но разработчики считают его устаревшим. В новых скриптах для каталогов лучше сразу использовать rsync или sftp.
Можно ли копировать через scp с паролем в скрипте?
Технически да, через sshpass, но так делать не стоит. Пароль будет виден в процессах и истории. Создайте отдельный ключ для скрипта, ограничьте его в authorized_keys и храните на сервере с правами 600.
Чем scp -r отличается от rsync -a?
scp -r каждый раз копирует всё заново и не сохраняет владельца и симлинки так, как rsync. rsync -a передаёт только изменения, сохраняет атрибуты и умеет продолжать после обрыва. Для повторных синхронизаций rsync выигрывает во всём.
Как скопировать файл с одного удалённого сервера на другой?
Самый простой вариант — scp -3 web1:/path/file web2:/path/: данные идут через вашу машину. Если серверы видят друг друга по сети, быстрее зайти на первый и запустить rsync оттуда. Для этого используйте проброс агента ssh -A только на доверенных серверах.
Как дать пользователю доступ только к файлам, без shell?
В sshd_config настройте блок Match User или Match Group с ForceCommand internal-sftp и ChrootDirectory. Каталог chroot должен принадлежать root и не быть доступным на запись другим. Такой пользователь сможет работать через sftp и новый scp, но не получит shell.