восстановить частично перезаписанную ленту из tar -c

восстановить частично перезаписанную ленту из tar -c

У меня возникла ситуация. Я должен был запустить tar -x, чтобы восстановить файл tar с ленты, но нажал "c" и забыл перевести ленту в режим "только для чтения". Файл находился на позиции fsf 23, но на ленте было 27 файлов. Я знаю, что файл 23 утерян, но поскольку я нажал ctrl+c, чтобы отменить команду tar, могу ли я все еще надеяться как-то восстановить другие файлы tar? Я попробовал fsf после файла 23, и все, что я получил, это ошибка ввода/вывода.

Я думал, может быть, сделать дамп из файла 23 с помощью dd, а затем получить этот файл и использовать инструмент восстановления файла подписи, например photorec. Это выполнимо?

решение1

Этот вопрос полностью зависит от устройства и его аппаратного обеспечения и соответствующего драйвера.

При неудачных операциях с лентой (например, прерывании записи) вы можете легко создать нечитаемый символ или даже нечитаемый участок на ленте. Вы уже показали, что ваш драйвер не способен читать дальше мусора, оставленного прерванной записью, поскольку mt fsfпросто выдает ioctl, который просит драйвер просто перейти к следующей метке EOF. Поскольку драйвер возвращает EIO, вы, скорее всего, не сможете заставить его работать лучше.

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

решение2

Попробуйте выполнить чтение, начиная с другого конца ленты:

#! /bin/sh
set -e
TAPE=/dev/... # change me, you must use a non-rewinding device.
export TAPE

# Wind to the end of the tape.
mt eod

# Rewind to the beginning of the last file and then list it.
# It's possible I misunderstood the way end-of-data is signaled
# on the tape and if so perhaps this command should be mt bsfm 2,
# in which case you can just combine this with the loop below.
# For context here you can look at the entry for MT_ST_TWO_FM
# in "man st".
mt bsfm 1
tar -f "$TAPE" -t

# We just read a file so we're  going to need to rewind over it
# and then rewind more to get to the beginning of the previous file.
# I forget whether tar leaves the tape at EOF or just after it. I'm
# assuming here just after, but if it leaves the tape at the EOF
# mark, the 2 on the next line would need to be a 1.
while mt bsfm 2 
do
  tar -f "$TAPE" -t
done

Это былосписоксодержимое всех архивов tar, к которым мы можем получить доступ с конца ленты. Конечно, есть также архивы в начале ленты, но вы можете перечислить их гораздо проще:

while tar -f "$TAPE" -t
do
  true
done

Операция mt eodпросит драйвер перемотать до конца ленты, перемотав мимо файловых меток. Это должно работать нормально, если все, что вы сделали для прерывания записи на ленту, это убили процесс tar с помощью SIGINT (Ctrl-C). С точки зрения драйвера ленты SCSI это выглядит так, как будто программа пользовательского пространства закрыла дескриптор файла, поэтому в этом месте должна быть метка EOF, но никакого фактического "повреждения".

Однако, если здесь происходит что-то еще и/или вышеописанный подход не работает, вы можете получить другой результат, попросив драйвер ленты сделать интервал до конца носителя, отправив команду SCSI на ленточный накопитель с просьбой сделать это. Это не то же самое, что поведение по умолчанию (которое заключается в том, что драйвер ленты делает интервал вперед по файлам, чтобы он мог отслеживать текущий номер файла (чтобы сообщать об операциях, таких как mt statusи mt tell). Чтобы настроить это, вы должны использовать ioctl MT_ST_FAST_EOM. Я не знаю, как это сделать из командной строки, вам может потребоваться создать небольшую программу на языке C, примерно такую:

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>

int main(int argc, char *argv[]) {
  (void)argc;
  (void)argv;
  struct mtop mt_cmd;
  mt_cmd.mt_op = MTSETDRVBUFFER;
  mt_cmd.mt_count = MT_ST_BOOLEANS | MT_ST_FAST_MTEOM;
  if (0 != ioctl(1, MTIOCTOP, &mt_cmd)) {
    perror("MTSETDRVBUFFER on stdout");
    return 1;
  }
  return 0;
}

Чтобы сэкономить на шаблоне, я предположил, что ленточное устройство уже открыто на стандартном выводе для этой программы (т.е. вы запускаете ее так: ./myprog >"$TAPE").

Я не тестировал этот код, пожалуйста, используйте его с осторожностью. Если он говорит вашим детям, что они могут завести щенка, не вините меня. Вы можете использовать другую программу на C, чтобы отменить настройку, но вы также можете просто перезагрузить машину, если постоянная доступность сервиса вас не беспокоит.

Связанный контент