- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF135:DrBrown3
Материал из Linuxformat.
Содержание |
Утилиты копирования
- Следуя древней мантре Perl «есть более чем один способ сделать это», мы открыли множество вариантов копирования файла.
Мой урок этого месяца – подлинное возвращение к истокам и одна из самых фундаментальных тем, которых я касался. Он посвящен копированию. Утилит для этой цели больше, чем вы можете счесть нужным, и мы рассмотрим полдюжины из них.
Начнем с начала, с команды cp. В простейшем случае она выглядит так:
$ cp файл-источник файл-назначение
Если последний аргумент cp – имя существующего каталога, в него можно скопировать несколько файлов одной командой. Список файлов генерируется по шаблону. Например, я хочу скопировать картинки Джо в формате JPEG в свой каталог images:
$ cp ~/joe/images/*.jpg images
Для столь несложной команды у cp поразительно много опций. Я упомяну три.
Опция -r (рекурсивно) копирует каталоги рекурсивно. Она позволяет скопировать целое поддерево файловой системы. Например, в итоге команды
$ cp -r /boot .
в текущем каталоге окажется полная копия дерева каталогов /boot.
Опция -a (архивировать) сохраняет атрибуты исходного файла, насколько это возможно. Например, если файл копируется суперпользователем-root, будут сохранены исходные права доступа и время изменения файла. При копировании файла обычным пользователем владельцем файла станет этот пользователь. Опция -a подразумевает -r.
Опция -b (резервная копия) велит cp создать резервную копию при перезаписи существующего файла. К имени файла резервной копии добавится ~.
Большой брат cp
scp (защищенное копирование) – старший брат cp. Этой командой можно копировать обычные файлы, как и cp, но основное ее назначение – копирование файлов с удаленных компьютеров по защищенному SSH-соединению. Выглядит она примерно так:
$ scp *.jpg james@servera.example.com:images james@servera.example.com’s password: storm1.jpg 100% 198KB 197.7KB/s 00:00 sunset1.jpg 100% 135KB 135.2KB/s 00:00 teaching1.jpg 100% 190KB 190.1KB/s 00:00 thegirls.jpg 100% 57KB 56.9KB/s 00:00 UNIX_highlighter.jpg 100% 80KB 80.1KB/s 00:00
Здесь мои файлы JPEG копируются в каталог images компьютера servera.example.com. james – имя моей учетной записи на сервере; если его опустить, будет взято имя пользователя, под которым я работаю на клиенте. Обратите внимание на двоеточие – это ключевой элемент конструкции, он сообщает команде, что я копирую файлы на удаленный компьютер. Имя каталога images интерпретируется относительно домашнего каталога пользователя james на сервере. Точно так же можно загружать файлы с удаленного компьютера. Можно даже делать «копирование от третьего лица», когда и исходный, и результирующий файл находятся на удаленных компьютерах.
Чтобы это работало, на удаленных компьютерах должен быть установлен и запущен демон SSH, и на них у вас должны быть учетные записи.
У scp есть опция рекурсивного копирования (-r) и опция сохранения атрибутов (-p). Есть также опция -C, включающая сжатие передаваемых данных, хотя, по моему опыту, в довольно быстрой сети это скорее замедлит, чем ускорит.
rsync
Изначально, rsync – утилита удаленной синхронизации, хотя ею можно пользоваться и как (цитирую man-страницу) «улучшенной командой копирования для повседневного использования». Так что мы можем просто копировать ею локальные файлы:
rsync файл-источник файл-назначение
Но славится rsync как средство удаленной синхронизации. Ее алгоритм дельта-пересылки значительно снижает объем пересылаемых по сети данных, отправляя только различия между исходными файлами и файлами, существующими на получателе.
Это великолепное средство резервного копирования и зеркалирования. По существу, вы говорите ей: «сделай эту файловую систему здесь точно такой же, как та вон там», и она делает это весьма эффективно. Синтаксис этой команды очень похож на синтаксис scp. Я могу скопировать весь мой архив статей Linux Format на удаленный сервер таким образом:
$ rsync -av Linux-Format-Articles servera.example.com: … тут будет много наименований … sent 68556777 bytes received 14403 bytes 5079346.67 bytes/sec total size is 68497001 speedup is 1.00
Если я сохраню файл, который сейчас пишу (он называется copying.txt) и повторю команду rsync, она завершится почти мгновенно, так как передает только различия между файлами:
$ rsync -av Linux-Format-Articles servera.example.com: sending incremental file list sent 21426 bytes received 161 bytes 4797.11 bytes/sec total size is 68497303 speedup is 3173.08
При копировании на удаленные компьютеры rsync может использовать SSH или подключаться к демону rsyncd.
rsync сама по себе – не средство резервного копирования промышленного уровня, но резервное копирование с помощью rsync на USB-брелок – прекрасное решение для индивидуальных пользователей-профессионалов.
wget
wget – неинтерактивная утилита командной строки для копирования файлов с URL-адресов по протоколам FTP, HTTP или HTTPS. Файл записывается в текущий каталог. Вот пример:
$ wget http://archive.ubuntu.com/ubuntu/ls-lR.gz --2010-06-14 13:43:57-- http://archive.ubuntu.com/ubuntu/ls-lR.gz Resolving archive.ubuntu.com… 91.189.88.46, 91.189.88.30, ... Connecting to archive.ubuntu.com… |91.189.88.46|:80… connected. HTTP request sent, awaiting response… 200 OK Length: 9190681 (8.8M) [application/x-gzip] Saving to: ‘ls-lR.gz’ 100% [==================================>] 9,190,681 763K/s in 12 s 2010-06-14 13:48:05 (758 KB/s) – ‘ls-lR.gz’ saved [9190681/9190681]
У wget тоже есть опция рекурсивного копирования (да, тоже -r), которая велит ей следовать ссылкам на HTML-страницах, по сути воссоздавая локальную копию структуры каталогов сайта. При этом содержимое копируется в каталог верхнего уровня с именем сайта. Например, команда
$ wget http://archive.ubuntu.com
скопирует содержимое сайта в каталог archive.ubuntu.com и будет делать это очень долго!
На практике wget -r работает только для статических сайтов, которых сейчас все меньше и меньше. Тем не менее, утилита очень удобна, когда нужно загрузить файлы с сайта из скрипта, или на сервере без браузера.
Из описанных утилит лишь wget работает только в одном направлении – с ее помощью можно скачать, но не закачать файлы. Однако для этой цели служит утилита wput, если вам интересно.
Причуды dd
Команда dd – безусловно, одна из самых странных бестий мира Linux. У нее причудливы и синтаксис, и набор возможностей. С ее помощью можно просто копировать файлы:
$ dd if=/boot/vmlinuz-2.6.32-22-generic of=foo 7886+1 records in 7886+1 records out 4037792 bytes (4.0 MB) copied, 0.0290523 s, 139 MB/s
но это слегка мимо кассы. Попутно утилита может выполнять всяческие немыслимые преобразования данных: например, перевести нижний регистр в верхний (и наоборот) или переделать кодировку ASCII в EBCDIC (и наоборот). (EBCDIC расшифровывается как Extended Binary Coded Decimal Interchange Code – расширенный двоично-десятичный код обмена информацией, эта кодировка введена IBM и больше никем не используется). Она может поменять местами чередующиеся байты и выровнять текстовые строки по длине. Некоторые из ее функций явно нацелены на миграцию данных между Unix/Linux и традиционными компьютерами IBM. Но, пожалуй, самая полезная возможность dd – контроль размера блоков, в которых будет считываться входной файл и записываться выходной, а также возможность задания числа копируемых блоков. Это дает почву для интересных экспериментов. Например, файл размером 1 МБ, полный нулей, можно создать так:
$ dd if=/dev/zero of=allzeros bs=1M count=1 1+0 records in 1+0 records out 1048576 bytes (1.0 MB) copied, 0.00476925 s, 220 MB/s
Здесь мы записываем один блок размером 1 МБ. Стиль указания файла-аргумента if=/dev/zero совершенно чужд Linux и не поддерживает спецсимволы (шаблоны). Обратите внимание на желание dd сообщать вам о том, какой объем данных скопирован и насколько быстро это произошло. Утилита также способна клонировать диск. Здесь, например, мы создаем образ раздела /dev/sda1 и записываем его в файл:
$ sudo dd if=/dev/sda1 of=sda1-image bs=64M 1+1 records in 1+1 records out 123346944 bytes (1.0 MB) copied, 0.00476925 s, 220 MB/s
Незваный гость
Последнее явление на вечеринке утилит копирования смахивает на незваного гостя: это скорее утилита архивирования, чем копирования. Зовут ее tar. Однако, направляя данные в tar и получая их оттуда, можно копировать иерархии файлов. Трюк состоит в том, чтобы указать ‘-‘ в качестве имени выходного или входного файла, что заставит tar писать в стандартный вывод или читать со стандартного ввода. Здесь я копирую свой каталог статей Linux Format в каталог /tmp:
$ tar cf - Linux-Format-Articles/ | (cd /tmp; tar xf -)
Точно так же можно создать канал через SSH-соединение и скопировать файлы на удаленные компьютеры:
$ tar cf - source-dir | ssh servera.example.com tar xf -
Держу пари, что вы до этого не додумались!
Что в имени тебе моем?
dd берет название из языка управления заданиями (JСL) мейнфреймов IBM – это сокращение от “data definition” [определение данных]. Оттуда же пришел и странный синтаксис, столь неудобный в командной строке Linux. Выглядел он примерно так:
//QSAM0080 DD DSN=FOOBAR.DATA.QSAM0080,DISP=OLD,KEEP
Я думаю, что смог подавить большую часть своих воспоминаний о борьбе с JСL в мои студенческие годы перфолент и перфокарт. Мне обычно гораздо труднее давались полдюжины строк на JСL, чем следующие за ними 200 строк на Fortran. Обычно я получал распечатку об ошибке (учтите, выдача была раз в полдня), гласившую «отсутствует запятая в строке 3». Много раз я дивился: почему, зная, что там не хватает запятой, компьютер не может просто представить, что она там есть, и двинуться дальше?