Cpio VS tar и cp

Я только что узнал, что cpio имеет три режима: копирование, копирование и прохождение.

Мне было интересно, каковы преимущества и недостатки cpio в режимах копирования и копирования через tar. Когда лучше использовать cpio и когда использовать tar?

Аналогичный вопрос для cpio в режиме сквозной передачи по сравнению с cp.

Спасибо и приветствую!

Ответ 1

Я не вижу причины использовать cpio по какой-либо причине, кроме копирования открытых файлов RPM, через disrpm или rpm2cpio, но могут быть угловые случаи, в которых cpio предпочтительнее tar.

История и популярность

Оба tar и cpio являются конкурирующие форматы архивов, которые были введены в версии 7 Unix в 1979 году и затем включены в POSIX.1-1988, хотя только один tar остался в следующем стандарте, POSIX.1-2001 1.

Формат файла Cpio несколько раз менялся и не оставался полностью совместимым между версиями. Например, в настоящее время существует кодированное ASCII представление данных информации о двоичном файле.

Тар более универсально известен, стал более универсальным с годами и, скорее всего, будет поддерживаться в данной системе. Cpio все еще используется в нескольких областях, таких как формат пакета Red Hat (RPM), хотя RPM v5 (что, по общему признанию, неясно) использует xar вместо cpio.

Оба живут на большинстве Unix-подобных систем, хотя tar чаще встречается. Вот Debian устанавливают статистику:

#rank  name    inst    vote    old  recent  no-files  (maintainer)
   13   tar  189206  172133   3707   13298        68  (Bdale Garbee)
   61  cpio  189028   71664  96346   20920        98  (Anibal Monsalve Salazar)

Режимы

Копирование: это для создания архива, сродни tar -pc

Копирование: это для извлечения архива, сродни tar -px

Проход. Это в основном оба вышеупомянутых, сродни tar -pc … |tar -px, но в одной команде (и, следовательно, микроскопически быстрее). Он похож на cp -pdr, хотя оба cpio и (особенно) tar имеют большую настраиваемость. Также рассмотрите rsync -a, который люди часто забывают, поскольку он более типично используется в сетевом соединении.

Я не сравнивал их производительность, но я ожидаю, что они будут очень похожи в размере процессора, памяти и архива (после сжатия).

Ответ 2

TAR (1) так же хорош, как cpio(), если не лучше. Можно утверждать, что он, по сути, лучше, чем CPIO, потому что он вездесущий и проверенный. Должна быть причина, по которой у нас везде есть шарики.

Ответ 3

Почему cpio лучше, чем tar? По ряду причин.

  • cpio сохраняет жесткие ссылки, что важно, если вы используете его для резервного копирования.
  • cpio не имеет этого раздражающего ограничения длины имени файла. Конечно, у gnutar есть "хак", который позволяет вам использовать более длинные имена файлов (он создает временный файл, в котором он хранит настоящее имя), но он по своей сути не переносится в не-gnu tar.
  • По умолчанию cpio сохраняет отметки времени
  • При написании сценариев он имеет гораздо лучший контроль над тем, какие файлы являются и не скопированы, поскольку вы должны явно перечислять файлы, которые хотите скопировать. Например, какое из следующего легче читать и понимать?

    find . -type f -name '*.sh' -print | cpio -o | gzip >sh.cpio.gz
    

    или в Solaris:

    find . -type f -name '*.sh' -print >/tmp/includeme
    tar -cf - . -I /tmp/includeme | gzip >sh.tar.gz
    

    или с помощью gnutar:

    find . -type f -name '*.sh' -print >/tmp/includeme
    tar -cf - . --files-from=/tmp/includeme | gzip >sh.tar.gz
    

    Несколько конкретных заметок здесь: для больших списков файлов вы не можете поместить поиск в обратные кавычки; длина командной строки будет превышена; вы должны использовать промежуточный файл. Отдельные команды find и tar по своей природе медленнее, так как действия выполняются серийно.

    Рассмотрим этот более сложный случай, когда вы хотите, чтобы дерево было полностью упаковано, но некоторые файлы в одном tar, а остальные файлы - в другом.

    find . -depth -print >/tmp/files
    egrep    '\.sh$' /tmp/files | cpio -o | gzip >with.cpio.gz
    egrep -v '\.sh$' /tmp/files | cpio -o | gzip >without.cpio.gz
    

    или в Solaris:

    find . -depth -print >/tmp/files
    egrep    '\.sh$' /tmp/files >/tmp/with
    tar -cf - . -I /tmp/with    | gzip >with.tar.gz
    tar -cf - .    /tmp/without | gzip >without.tar.gz
    ##          ^^-- no there no missing argument here.  It just empty that way
    

    или с помощью gnutar:

    find . -depth -print >/tmp/files
    egrep    '\.sh$' /tmp/files >/tmp/with
    tar -cf - . -I /tmp/with    | gzip >with.tar.gz
    tar -cf - . -X /tmp/without | gzip >without.tar.gz
    

    Опять же, некоторые примечания: Отдельные команды find и tar по своей сути медленнее. Создание более промежуточных файлов создает больше помех. gnutar чувствует себя немного чище, но параметры командной строки по своей сути несовместимы!

  • Если вам нужно скопировать много файлов с одного компьютера на другой, спеша через сеть занятых, вы можете запускать несколько cpio параллельно. Например:

    find . -depth -print >/tmp/files
    split /tmp/files
    for F in /tmp/files?? ; do
      cat $F | cpio -o | ssh destination "cd /target && cpio -idum" &
    done
    

    Обратите внимание, что это поможет, если вы можете разделить вход на части размером. Для этого я создал утилиту под названием "npipe". npipe будет читать строки из stdin и создавать N выходных каналов и кормить строки для них, поскольку каждая строка будет потребляться. Таким образом, если первая запись была крупным файлом, на который ушло 10 минут, а остальные были небольшими файлами, на которые потребовалось 2 минуты для передачи, вы не застопорились, ожидая большого файла плюс еще десяток небольших файлов, стоящих в очереди за ним, Таким образом, вы заканчиваете расщепление по требованию, а не строго по количеству строк или байтов в списке файлов. Подобная функциональность может быть реализована с помощью параллельной возможности разворота gnu-xargs, за исключением того, что вместо аргументов в командной строке помещаются аргументы в командную строку.

    find . -depth -print >/tmp/files
    npipe -4 /tmp/files 'cpio -o | ssh destination "cd /target && cpio -idum"'
    

    Как это происходит быстрее? Почему бы не использовать NFS? Почему бы не использовать rsync? NFS по своей сути очень медленная, но что более важно, использование любого отдельного инструмента по сути является однопоточным. rsync читает в исходном дереве и записывает в дерево назначения по одному файлу за раз. Если у вас многопроцессорная машина (в то время, когда я использовал 16cpu на машину), параллельное письмо стало очень важным. Я ускорил копию дерева 8 ГБ до 30 минут; что 4.6MB/sec! Уверен, что это звучит медленно, так как 100-мегабитная сеть может легко делать 5-10 Мбайт/с, но это время создания inode, которое делает его медленным; в этом дереве было легко 500 000 файлов. Поэтому, если создание inode является узким местом, мне нужно было распараллелить эту операцию. Для сравнения, копирование файлов в однопоточном режиме займет 4 часа. Это в 8 раз быстрее!

    Вторая причина, по которой это происходит быстрее, заключается в том, что параллельные tcp-каналы менее уязвимы для потерянного пакета здесь и там. Если одна труба застопорилась из-за потерянного пакета, остальные, как правило, не будут затронуты. Я не совсем уверен, насколько это изменило ситуацию, но для тонких многопоточных ядер это снова может быть более эффективным, поскольку рабочая нагрузка может быть распределена по всем этим

По моему опыту, cpio выполняет более совершенную работу, чем tar, а также переносит больше аргументов (аргументы не изменяются между версиями cpio!), хотя их можно найти не на некоторых системах (не установленных по умолчанию на RedHat), но опять же Solaris не поставляется с gzip по умолчанию.