Занимаясь веб-разработкой мы часто сталкиваемся с такой типовой задачей: надо забрать с клиентского хостинга сайт, что-то там покрутить, вернуть обновлённую версию обратно. При этом клиентские виртуальные хостинги бывают разные: не на каждом есть SSH или SFTP доступ. Зато старый пыльный FTP есть везде. Если задача простая и затрагивает 1-2 файла, то их «забирает» напрямую программист к себе в IDE, редактирует и выгружает обновления на боевой хост, благо современные IDE снабжены FTP-клиентами. Но если задача требует экспериментов или тестирования, то на боевом клиентском хостинге её решать нельзя стыдно, надо делать «зеркало» у себя. А значит необходим удобный инструмент, позволяющий забрать файлы сайта к себе на сервер по FTP и потом выгрузить их обратно. Задачу блестяще решает консольный FTP-клиент lftp
.
Вообще мы долго обходились возможностями mc
, но наш серверный администратор на него ругается, не рекомендует через него лазить по многогигабайтным tar`ам, качать большие сайты по FTP и т.д. И также сразу отмечу, что идейно верным решением был бы rsync
, но из-за того, что не к любому виртуальному хостингу его применишь — он не подходит тоже. Поэтому вернёмся к герою сегодняшнего обзора.
В Ubuntu из коробки lftp
отсутствует, поэтому для начала экспериментов надо его установить. Как обычно:
sudo apt-get install lftp
Далее можно смело запускать программу, для удобства сразу же передав ей реквизиты удалённого хоста в формате логин:пароль@хост (такой же стандарт используется в mc
и вообще описан в RFC 1738):
lftp ftp://user:PassW0rd@example.com
После успешного коннекта вас ждёт приглашение вида:
lftp user@example.com:~>
Теперь вы можете вводить команды в интерактивном режиме. К счастью, запомнить придётся только несколько самых простых и понятных команд, потом сразу перейдём к самому вкусному.
exit
— выход из lftppwd
— вывод текущего пути на удалённом сервере (в общем, помогает узнать, где вы находитесь в структуре файлов и каталогов)ls
— листинг текущей директории на удалённом сервереls -al
— листинг с расширенными параметрами представления (объём, права и т.п.)cd dir
— переход в директорию dir на удалённом сервереlpwd
— вывод текущего пути на локальной машине (куда по умолчанию будут скачиваться файлы и директории или откуда закачивать на удалённый сервер)lcd dir
— переход в директорию dir на локальной машине!ls
— листинг текущей директории на локальной машине (на самом деле, вы можете после!
написать любую команду и она будет выполнена локально: например, вместоlpwd
можно использовать!pwd
)!ls -al
— ну, вы понялиget file
— скачать file из текущей директории удалённого сервера в текущую локальную директорию (file может быть не только относительным, но и абсолютным именем, что конечно же позволяет забирать файл не обязательно из текущей директории)get rfile -o lfile
— скачать rfile с удалённого сервера и сохранить на локальном как rfileput file
— закачать file из локальной директории на удалённый серверput lfile -o rfile
— закачать lfile на удалённый сервер как rfilehelp
— справка по доступным командам (вы удивитесь, но среди команд естьtorrent
— и, да, это простенький встроенный торрент-клиент)
Перечисленного выше минимума хватит чтобы освоиться и что-то сделать руками. Но руками придётся делать немногое, поскольку мы переходим к самому вкусному — команде mirror
. Простейшие примеры использования:
mirror public_html
— синхронизирует директорию public_html с удалённого сервера на локальный, включая все поддиректории и файлы, с сохранением прав и всего такого прочегоmirror -R public_html
— синхронизирует директорию public_html в обратном направлении, с локальной машины на удалённую
Тут с удовольствием поясню, что значит «синхронизирует». При первом запуске будет произведено полное рекурсивное копирование. Но при повторных запусках передаваться по сети будут только те файлы, которые изменились с момента предыдущей синхронизации. Насколько я понял, факт изменения устанавливается по двум параметрам: дата последнего сохранения файла и его объём. Никакие хеши, конечно, не считаются, но и без с них, к счастью, мы сильно сокращаем скорость синхронизации и объём передаваемых данных.
Вот пример отчёта о первой синхронизации (скачивании) довольно большого сайта в несколько гигабайт:
Total: 1307 directories, 48196 files, 0 symlinks New: 48196 files, 0 symlinks
3962870501 bytes transferred in 495 seconds (7.64M/s)
Зато повторный запуск и выполнение той же команды занимает несколько секунд (в этом конкретном случае около 20). И отчёт мы получаем примерно такой:
Total: 1307 directories, 48196 files, 0 symlinks
New: 10 files, 0 symlinks
В итоге в нашем распоряжении оказывается современный механизм (синхронизация) поверх древних технологий (FTP). И это отлично!
В интерактивный режим lftp входить не обязательно, можно из локальной консоли сразу дать такую команду, чтобы директорию синхронизировалась, например:
lftp -e 'mirror -c public_html /var/www/testsite/public_html; bye;' ftp://user:PassW0rd@example.com
Ключ -e
для lftp
позволяет указать команду(ы) для выполнения, а после команд идёт хост с реквизитами доступа.
Параметром ключу -e
мы в кавычках передаём последовательность команд, сначала команду mirror
, она будет синхронизировать контент из удалённой папки ./public_html
в локальную /var/www/testsite/public_html
, потом FTP-команду bye
— для закрытия соединения.
Ключ -с
для команды mirror активирует докачку (поэтому его лучше всегда использовать).
Для верности дам ещё один пример, в котором мы обратно на удалённый сервер синхронизируем данные из локальной директории (например, после того, как изменим пару файлов локально):
lftp -e 'mirror -c -R /var/www/testsite/public_html public_html; bye;' ftp://user:PassW0rd@example.com
Разница тут в том, что мы добавили уже известный ключ -R
, ну и поменяли местами каталоги (сначала указывается откуда, а потом куда синхронизировать).
Можно любую последовательность команд вынести в отдельный файл и запустить lftp с ключом -f
для выполнения этой последовательности:
lftp -f commands.ftp
Контент commands.ftp
может быть таким (для примера выполню там те же действия, что и в предыдущем запуске):
open ftp://user:PassW0rd@example.com mirror -c -R /var/www/testsite/public_html public_html
exit
В интерактивном режиме lftp позволяет легко устанавливать кодировки для удалённого сервера. Вот так:
set ftp:charset cp1251
Ещё одна полезная опция (которая по умолчанию добавляет ключ -a
к FTP-команде LIST
на удалённом сервере, в результате чего начинают видеться и копироваться «скрытые» файлы и папки, названия которых начинаются с точки):
set ftp:list-options -a
Вообще команда set
позволяет на лету и на время перенастраивать lftp
не лазя руками в конфиг. Все действующие параметры конфига можно посмотреть так:
set -a
Базовый конфиг хранится в /etc/lftp.conf
, а логи и история хранятся в директории ~/.lftp
отдельно для каждого пользователя.
Могу вам порекомендовать в базовом конфиге раскомментировать вот эти две строчки (ищите их ближе к концу файла /etc/lftp.conf
):
set at-exit "set > ~/.lftp/settings"
source ~/.lftp/settings
Тогда все настройки, задаваемые через set
будут сохранятся перед выходом из lftp
.
Кроме упомянутого торрент-клиента в lftp
есть ещё много примочек, например, очереди (см. help queue
в интерактивном режиме) и альясы (см. help alias
). lftp умеет работать с протоколами FTPS, FISH и SFTP, т.е. если к файловой системе хостинга есть хоть какой-то доступ, то lftp вам поможет забрать и выгрузить файлы. А ещё lftp поддерживает FXP — это протокол, позволяющий передавать файлы с одного FTP-сервера на другой напрямую, не копируя их на локальную машину. В lftp такая передача реализуется командой типа get ftp://... -o ftp://...
Надеюсь, что lftp
пропишется у вас если уж не на боевом сервере, то хотя бы на сервере для разработки.
»