Разница между `exit;` и `exit $?;`

Хорошо, думаю, я разобрался с этим.

TL;DR

Вместо этого используйте ddс большим размером блока для чтения с ленты:

dd if=/dev/nst0 bs=1M | tar tvf -

Фон

При записи на ленты данные записываются блоками, называемыми блоками. Это как сектора на жестком диске. В то время как блоки жесткого диска были зафиксированы на уровне 512 -байт в течение многих лет и только недавно были переведены на блоки размером 4096 -байт, блоки ленты могут быть установлены любого размера, который вам нравится.

Размер блока, который вы хотите использовать, устанавливается с помощью подкоманды setblkв mt-st:

.

mt-st -f /dev/nst0 setblk 512    # Use 512-byte blocks
mt-st -f /dev/nst0 setblk 64k    # Use 65536-byte blocks

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

Это означает, что если используемая вами программа предоставляет буфер памяти размером 16 КБ, вы сможете считывать до 32 блоков за раз с ленты с блоками по 512 -байтов, поскольку они точно помещаются в буфер 16 КБ. Однако вы не сможете прочитать ничего с ленты с блоками по 64 КБ, потому что вы не можете поместить даже один из них в буфер 16 КБ, и помните, что вы не можете прочитать что-либо меньше, чем один целый блок вовремя.

Если вы попытаетесь сделать это, используя буфер, который слишком мал для одного блока, драйвер (в данном случае stдрайвер ленты SCSI )вернет код ошибки выделения памяти, чтобы сообщить вам, что ваш буфер чтения слишком мал, чтобы вместить даже один блок.

Еще больше усложняет ситуацию то, что некоторые ленточные накопители (, по-видимому, LTO, которые я использую ), также поддерживают блоки переменного -размера. Это означает, что размер блока определяется размером каждой операции записи , и размер каждого блока может отличаться от последнего.

Этот режим устанавливается с нулевым размером блока:

mt-st -f /dev/nst0 setblk 0    # Use variable-sized blocks

Это также вариант по умолчанию, так как -предположительно, здесь -я предполагаю, что он занимает меньше места при неправильно настроенной программе. Если, например, вы установили блоки размером 4 КБ, но ваша программа записывала данные только блоками по 512 байт за раз, существует риск того, что каждый блок данных размером 512 -байт займет на ленте 4 КБ.

Причина

Если вы теперь соберете все вместе, вы поймете, что лента может гипотетически иметь блок размером 512 -байт, за которым следует блок размером 64 КБ. Если программа читает ленту с буфером 16 КБ, она успешно прочитает первый блок, но затем, когда она попытается прочитать больше, она не сможет поместить следующий блок 64 КБ в свой буфер, поэтому драйвер вернет ошибка.

Это объясняет, почему большую часть времени я получал ошибки Cannot allocate memory, и иногда мне удавалось заставить tar извлечь первые несколько файлов, но затем я снова получал ошибку. Я не установил размер блока с помощью mt-st, поэтому по умолчанию он был установлен на блоки переменного размера -при записи на ленту, и теперь tarиспользует слишком маленький буфер для чтения некоторых из этих блоков.

tarимеет пару опций для установки собственных внутренних размеров блока, а именно --blocking-factor, --read-full-recordsи --record-size, однако они работают, только если tarиспользуется для прямого чтения и записать в ленту.

Поскольку я записал на ленту через программуmbufferдля уменьшения свечения башмака ленты -, размер блока в архиве tarбольше не соответствовал размеру блока на ленте. Это означало, что --blocking-factorимеет мало эффекта -он позволит прочитать первый блок на ленте, который включает в себя заголовок, сообщающий tarкакой коэффициент блокировки предполагается , в котором он переключается к этому и игнорирует значение, указанное в командной строке. Это означает, что второй и последующие блоки больше не могут быть прочитаны!

Решение

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

ddработает для этого, и в крайнем случае это работает:

dd if=/dev/nst0 bs=256k | tar tvf -

Возможно, вам придется увеличить 256k, если на вашей ленте есть блоки большего размера, но мне это помогло. 1Mтакже работает нормально, поэтому не имеет значения, слишком ли велико значение в разумных пределах.

1
08.11.2017, 18:47
0 ответов

Теги

Похожие вопросы