Мы — долго запрягаем, быстро ездим, и сильно тормозим.

FreeBSD
  настройка
  подсчёт трафика
  программы
  почтовые системы
  Шелезяки
  Мелочи
  Файловая система
  mount_nullfs
  badsect
  clri
  bsdlabel
  dump (rdump)
  dumpfs
  ffsinfo
  fsirand
  mount_nfs
  mount_smbfs
  swapon
  tunefs
  umount
  recovery files
  growfs
  Pax
  clonehdd
  Мониторинг RAID
  gstripe
  fusefs-ntfs
  UFS->ZFS
  RAID5
  freebsd lvm
  root ZFS, GPT
  FreeBSD on flash
  Восстановление ZFS
  Лечим FFS
  gmirror
  WWW
  Security
  system
  Games Servers
  X11
  Programming
Очумелые Ручки
OpenBSD
Cisco


www.lissyara.su —> статьи —> FreeBSD —> Файловая система —> Восстановление ZFS

Восстановление ZFS-пула с помощью подручных средств

Автор: BlackCat.


Оглавление

  • Введение
  • 1. Предыстория
  • 2. Восстановление
  • 2.1. Рекогносцировка местности
  • 2.2. Некоторые сведения об устройстве ZFS
  • 2.3. Детальное обследование пациента
  • 2.4. Тяжёлая артиллерия
  • 2.5. Поиск ответов в коде реализации
  • 2.6. Решение грубой силой
  • Год спустя
  • Мораль
  • Список литературы

                                                    Фарш нельзя провернуть назад.
                                                          Слоган радиопередачи
                                                                   "Литрофарш".

    Введение

    Представленный материал ни в коем случае не является инструкцией по восстановлению или чем-то похожим на инструкцию. Это просто рассказ о решении одной не тривиальной, для меня, задачи. И доказательство того факта, что ZFS вполне может быть восстановлена даже когда её драйвер утверждает, что пора доставать резервную копию т.к. все данные превратились в фарш, а фарш... О том, что нельзя сделать с фаршем читайте в эпиграфе. Текст написан в неформальном стиле, что бы подчеркнуть антинаучность представленного материала.

    1. Предыстория

    Был RAID-Z-пул собранный из трёх дисков по 1.5 Тб фирмы X, модели Y. Работал он работал, и изредка стали появляться в логах сообщения о том, что произошла ошибка чтения или ошибка записи на один из дисков пула. ZFS, ругаясь в логи на ошибки контрольных сумм, отлично отрабатывала такие моменты и пул продолжал нормально функционировать со статусом "ONLINE". Ошибки повторялись, но были не систематичными: различные диски, различные сектора, различное время. Назвав ошибки идиопатическими (неизвестной природы) решил, что обязательно разберусь с ними, но не сейчас. Эпик фейл подкрался незаметно, но всё же наступил. В один, не самый удачный момент, после перезагрузки, файловая система не cмонтировалась.

    Листинг 1.1. Развалившийся пул с почти отказавшим диском
    ~# zpool import
      pool: storage
        id: 15607890160243212464
     state: FAULTED
    status: The pool metadata is corrupted.
    action: The pool cannot be imported due to damaged devices or data.
            The pool may be active on another system, but can be imported using
            the '-f' flag.
       see: http://www.sun.com/msg/ZFS-8000-72
    config:
    
            storage     FAULTED  corrupted data
              raidz1    ONLINE
                ad2     ONLINE
                ad4     OFFLINE
                ad6     ONLINE
    


    При попытке импорта пула, zpool(8) вообще сваливался в кору.

    Листинг 1.2. Падение zpool(8) в кору
    ~# zpool import -o ro storage
    internal error: Illegal byte sequence
    Abort (core dumped)
    


    В логах стабильно появлялись два сообщения, свидетельствующие о том, что некоторые сектора на ad4 приказали долго жить. Как выяснилось далее, в этих секторах начинались важные для ZFS структуры данных, но первые несколько килобайт этой структуры, удачным образом, не использовались и были помечены в спецификации, как "Blank space" (пустое место).

    Примечание.
    Здесь и далее под килобайтом понимается 1024 байта, размер сектора так же стандартный, т.е. 512 байт.

    Листинг 1.3. Сбойные сектора
    ad4: FAILURE - READ_DMA48 status=51<...> error=40<UNCORRECT...> LBA=2930275840
    ad4: FAILURE - READ_DMA48 status=51<...> error=40<UNCORRECT...> LBA=2930276352
    


    Попробовал прочитать эти сектора и убедился в том, что они работать не будут.

    Листинг 1.4. Чтение сбойных секторов "в ручную"
    ~# dd if=/dev/ad4 of=/dev/null bs=512 skip=2930275840
    dd: /dev/ad4: Input/output error
    0+0 records in
    0+0 records out
    0 bytes transferred in 2.777067 secs (0 bytes/sec)
    


    Подключил диск такой же модели и в несколько приёмов (обходя сбойные сектора) скопировал на него содержимое глючившего диска. После чего поставил новый диск вместо глючного и попытался импортировать пул. Но, к моему разочарованию, пул отказался импортироваться и с новым диском. zpool(8) продолжал падать в кору.

    Листинг 1.5. Развалившийся пул, после замены диска
    ~# zpool import
      pool: storage
        id: 15607890160243212464
     state: FAULTED
    status: The pool metadata is corrupted.
    action: The pool cannot be imported due to damaged devices or data.
            The pool may be active on another system, but can be imported using
            the '-f' flag.
       see: http://www.sun.com/msg/ZFS-8000-72
    config:
    
            storage     FAULTED  corrupted data
              raidz1    ONLINE
                ad2     ONLINE
                ad4     ONLINE
                ad6     ONLINE
    


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

    2. Восстановление

    2.1. Рекогносцировка местности

    Внутреннее устройство ZFS я знал плохо - пришлось изучать его на форсаже, с прицелом на возможность восстановления данных. После недолгих поисков нагуглил[1] сообщение некоего Nathan Hand, который утверждал, что смог восстановить работоспособность пула. Так же в сообщении обнаружилась ссылка на черновой вариант спецификации[2] ZFS. Настроение стало улучшаться.

    2.2. Некоторые сведения об устройстве ZFS

    Тем, кто знаком с устройством ZFS этот раздел будет бесполезен, тем, кто не знаком - этот раздел будет даже вреден, лучше читать оригинальную спецификацию. Но, по-традиции, несколько слов об устройстве ZFS, как понял его я.

    Структура данных, с которой начинается разбор бинарного месива диска перед тем как это месиво станет навороченной файловой системой, называется метка (англ. Label). На диске хранится несколько меток в строго определённых позициях.

    Схема 2.2.1. Расположение меток на диске
      +----+----+--------------------+----+----+
      | L0 | L1 |                    | L2 | L3 |
      +----+----+--------------------+----+----+
    


    L0, L1, L2, L3 - метки ZFS. L0, L1 - располагаются друг за другом без пропусков в начале диска (с нулевого смещения). L2, L3 - располагаются в конце диска, но не обязательно в самых последних секторах, после них может оставаться свободное место (скорее всего из-за выравнивания на 128 Кб). Пространство между L1 и L2 занято вспомогательными структурами и самими данными, но их позиции строго не определены. Метки на одном диске должны быть строго одинаковыми. О том, почему выбрано такое количество меток и каким образом они обновляются хорошо написано в документации[2].

    Структура метки достаточно проста, она состоит из 8Кб пустого пространства (англ. Blank Space), 8Кб загрузочного заголовка (англ. Boot Header), 112Кб конфигурационных данных в формате имя - значение (англ. Name/Value Pair List) и 128Кб массива структур Uberblock. Итого получается 256Кб на одну метку.

    Схема 2.2.2. Структура метки
        Blank    Boot       Name/Value              Uberblock
        Space   Header      Pair List                 Array
      +-------+--------+----------------+---------------------------------+
      |       |        |                | | | | | | | | | | | |  ...  | | |
      +-------+--------+----------------+---------------------------------+
      0       8K      16K              128K                              256K
    


    Список имя-значение, содержит следующие конфигурационные данные (перечислены самые интересные, на мой взгляд):
    - version - версия формата хранения;
    - name - имя пула;
    - state - состояние пула (активен/экспортирован/удалён);
    - txg - номер транзакции в которой выполнялась запись (будет описан далее);
    - pool_guid - уникальный идентификатор пула;
    - guid - уникальный идентификатор виртуального устройства;
    - vdev_tree - дерево, описывающее всю конфигурацию входящих в пул виртуальных устройств, само дерево состоит из пар имя-значение, основные поля описывающие отдельное устройство:
      - type - тип устройства (файл/блочное устройство/зеркало/raidz/корень);
      - path - имя устройства (только для файлов и блочных устройств);
      - guid - уникальный идентификатор описываемого виртуального устройства;
      - children - массив подчинённых виртуальных устройств.

    Более подробное описание самих данных и ссылки на формат их хранения доступны в спецификации.

    Примечание.
    Следует отметить, что ZFS активно оперирует таким понятием, как виртуальное устройство (англ. vdev), под которым может пониматься, как вполне реальный диск, так и абсолютно абстрактный RAID-Z массив или корень иерархии устройств.

    Uberblock (перевода не придумал) по своей природе похож на Superblock UFS - он является началом всей структуры данных на диске. Почему используется целый массив блоков вместо одного? Всё просто: ZFS никогда не пишет данные поверх уже существующих, вместо этого она записывает новую структуру в новую позицию, и только потом допускает возможность модификации уже имеющихся данных (их перезапись). При чтении структуры диска (напр. после перезагрузки) просто находится запись сделанная последней и используется, остальные записи считаются неактуальными. Сам Uberblock в начале содержит пять 64-битных полей:
    - ub_magic - "магическое число" идентифицирующее (сигнатура) блок;
    - ub_version - версия формата хранения;
    - ub_txg - номер транзакции в которой записана данная структура;
    - ub_guid_sum - сумма идентификаторов устройств;
    - ub_timestamp - UTC метка времени.

    Далее следуют указатели на подчинённые структуры. Суммарный объём структуры равен 1Кб. С учётом того, что массив имеет объём 128Кб получаем, что в каждой метке может храниться 128 Uberblock'ов, созданных в разное время.

    "Магическое число" всегда равно 0x00bab10c (oo-ba-block) на диск данное значение будет записано следующей последовательностью байт.

    Таблица 2.2.1. Запись "Магического числа"
     +----------------+-------------------------+
     | Edians         | Bytes                   |
     +----------------+-------------------------+
     | Little (x86)   | 0c b1 ba 00 00 00 00 00 |
     | Big (Sparc)    | 00 00 00 00 00 ba b1 0c |
     +----------------+-------------------------+
    


    Особого внимания заслуживает поле транзакция, в котором хранится номер транзакции, по завершении которой и был записан данный Uberblock. Так же, как было отмечено ранее, номер транзакции отдельно указывается в метке. На основании этого номера и принимается решение, какой Uberblock считается активными. Активным считается Uberblock с максимальным номером транзакции, при этом номер транзакции блока должен быть больше и равен номеру транзакции метки. Если это условие не выполняется, то производится поиск блока с меньшим номером. Т.о. если при выполнении транзакции произошла ошибка и Uberblock записан не был, то ZFS сможет корректно откатиться к предыдущей транзакции.

    Для просмотра содержимого меток диска используется опция "-l" утилиты zdb(8).

    Дальше начинаются дебри из структур, описывающих расположение блоков на диске. Кому интересно, тот может ознакомиться с ними в документации[2].

    2.3. Детальное обследование пациента

    Начать было решено с простейших манипуляций - проверить читаемость и корректность меток, с помощью zdb(8).

    Листинг 2.3.1. Чтение меток с дисков (показано только начало дампа)
    ~# zdb -l /dev/ad2
    --------------------------------------------
    LABEL 0
    --------------------------------------------
        version=14
        name='storage'
        state=0
        txg=253277
        pool_guid=15607890160243212464
    ...
    ~# zdb -l /dev/ad4
    --------------------------------------------
    LABEL 0
    --------------------------------------------
        version=14
        name='storage'
        state=0
        txg=247242
        pool_guid=15607890160243212464
    ...
    ~# zdb -l /dev/ad6
    --------------------------------------------
    LABEL 0
    --------------------------------------------
        version=14
        name='storage'
        state=0
        txg=253277
        pool_guid=15607890160243212464
    ...
    


    Никакого криминала метки считались - придётся вводить в действие тяжёлую артиллерию.

    2.4. Тяжёлая артиллерия

    Для того, что бы было удобнее копаться в бинарном содержимом меток их необходимо было скопировать с дисков в отдельные файлы. Для этого нужно знать начала меток и их размер на диске. С размером вопросов не было - размер меток постоянен и равен 256Кб. Смещения L0 и L1 равны 0 и 256Кб соответственно. Оставалось выяснить смещения L2 и L3. Объём диска равен 1465138584Кб, вычитая размер метки, я должен был получить смещение метки L3: 1465138328Кб. Но не тут то было. Сделав дамп 256Кб от полученного смещения я решил его проверить, найдя смещение первого Uberblock'а от начала дампа. Это должно было быть ровно 128Кб или 020000h. Uberblock легко определить в куче байт по "Магическому числу", с которого он начинается, но необходимо делать поправку на порядок байт в записи числа.

    Листинг 2.4.1. Неправильный выбор смещения
    ~# dd if=/dev/ad2 of=tmp.dump bs=1024 count=256 skip=1465138328
    256+0 records in
    256+0 records out
    262144 bytes transferred in 0.057129 secs (4588621 bytes/sec)
    ~# od -t xC -A x tmp.dump | grep "0c  b1  ba  00" | head -n 1
    0000000    0c  b1  ba  00  00  00  00  00  0e  00  00  00  00  00  00  00
    


    Промазал. Первый Uberblock в полученном дампе располагался на нулевом смещении, а это значит, что ошибка составляет минимум 128Кб. Т.к. первый Uberblock должен располагаться на смещении 128Кб от начала метки, а в дампе уже на нулевом смещении я видел один из блоков. Для определения корректного смещения было необходимо определить, сколько Uberbock'ов попало в дамп и сместиться на соответствующее количество блоков + 128Кб.

    Листинг 2.4.2. Определение количества Uberblock'ов, попавших в дамп
    ~# dd if=/dev/ad2 of=tmp.dump bs=1024 count=256 skip=1465138328
    256+0 records in
    256+0 records out
    262144 bytes transferred in 0.057163 secs (4585903 bytes/sec)
    ~# od -t xC -A x tmp.dump | grep "0c  b1  ba  00" | wc -l
         104
    


    В дампе 104 блока, должно быть 128 - нам надо сместиться влево (к младшим адресам) на: (128 - 104) + 128 = 152 (Кб). Новое смещение: 1465138328 - 152 = 1465138176 (Кб). Делаем дамп и проверяем количество блоков и смещение первого из них.

    Листинг 2.4.3. Проверка нового смещения
    ~# dd if=/dev/ad2 of=tmp.dump bs=1024 count=256 skip=1465138176
    256+0 records in
    256+0 records out
    262144 bytes transferred in 0.057357 secs (4570387 bytes/sec)
    ~# od -t xC -A x tmp.dump | grep "0c  b1  ba  00" | head -n 1
    0020000    0c  b1  ba  00  00  00  00  00  0e  00  00  00  00  00  00  00
    ~# od -t xC -A x tmp.dump | grep "0c  b1  ba  00" | wc -l
         128
    


    Ага, угадал. Смещение L2 получить элементарно - необходимо вычесть 256Кб из полученного смещения L3: 1465138176 - 256 = 1465137920 (Кб). Получилась небольшая таблица смещений. Т.к. диски одинаковой модели, то и смещения для них будут одинаковыми.

    Таблица 2.4.1. Смещения меток
     +----+-------------+
     | L# | Offset (Kb) |
     +----+-------------+
     | L0 | 0           |
     | L1 | 256         |
     | L2 | 1465137920  |
     | L3 | 1465138176  |
     +----+-------------+
    


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

    Листинг 2.4.4. Скрипт для дампа
    #!/bin/sh
    
    L0_OFF=0
    L1_OFF=256
    L2_OFF=1465137920
    L3_OFF=1465138176
    
    DISKS="ad2 ad4 ad6"
    
    for DISK in $DISKS; do
      echo "Dump labels from: $DISK"
      l=0
      for OFF in $L0_OFF $L1_OFF $L2_OFF $L3_OFF; do
        fdump="$DISK-label$l.dump"
        echo "  Label: $l (out: $fdump, offset: $OFF)"
    
        # Create output file
        touch "$fdump"
    
        # Dumping
        dd if="/dev/$DISK" of="$fdump" bs=1024 count=256 skip=$OFF 2> /dev/null
    
        l=`expr $l + 1`
      done
    done
    


    После его выполнения метки были сохранены в файлы adN-labelX.dump (N - номера дисков: 2, 4, 6; X - номер метки: 0, 1, 2, 3). Разбираться стало немного удобнее.

    Далее я начал сравнивать конфигурации, записанные в метках, но результата это не принесло - оставалось лезть в код реализации ZFS для того, что бы выяснить какие именно данные были повреждены.

    2.5. Поиск ответов в коде реализации

    Немного порывшись по коду zpool и libzfs, обнаружил следующие строки в libzfs_status.c, которые и устанавливают статус пула "The pool metadata is corrupted".

    Листинг 2.5.1. Код определяющий состояние ZFS-пула
      /*
       * Corrupted pool metadata
       */
      if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
          vs->vs_aux == VDEV_AUX_CORRUPT_DATA)
        return (ZPOOL_STATUS_CORRUPT_POOL);
    


    Проверяемые поля устанавливаются в модуле ядра - пришлось перебираться в ядро. После недолгих поисков был найден файл spa.c, ответственный за открытие/закрытие, а так же импорт пула. В данном файле было несколько участков кода, в которых поля устанавливались в интересующее состояние. Надо было как-то выяснить что именно не нравиться алгоритму импорта. Для этого насовал кучу отладочного вывода в модуль, пересобрал его и загрузил вместо стандартного, разрешив вывод отладочной информации. Теперь, в момент импорта пула, в логи сыпалось множество отладочной информации, показывающей ход выполнения алгоритма импорта/открытия пула. Среди прочего был найден код проверки активного Uberblock'а.

    Листинг 2.5.2. Проверка активного Uberblock'а
      /*
       * If we weren't able to find a single valid uberblock, return failure.
       */
      if (ub->ub_txg == 0) {
        vdev_set_state(rvd, B_TRUE, VDEV_STATE_CANT_OPEN,
            VDEV_AUX_CORRUPT_DATA);
    


    Примечание.
    У zpool(8) есть специальная недокументированная опция "-F", которая позволяет импортировать даже сбойный пул. Работать после этого он конечно не будет, но для отладки и восстановления данных опция полезная.

    Добавив перед проверкой вывод номера транзакции активного блока, получил номер транзакции, которую ZFS считает последней удачной. Это была 253277 транзакция.

    Немного порывшись в коде, пришёл к выводу, что ошибка где-то глубже чем неправильно записанная метка. Т.к. восстанавливать всю структуру блок за блоком в мои планы не входило (пул содержал несколько сотен гигабайт не такой уж и ценной информации), я решил прибегнуть к грубой силе - заставить ZFS откатиться к предыдущей транзакции.

    2.6. Решение грубой силой

    Для того, что бы заставить ZFS откатиться к предыдущему состоянию, было необходимо стереть Uberblock последней удачной транзакции (а это была 253277 транзакция). Но прежде, немного переделав предыдущий скрипт, я получил скрипт извлекающий номера транзакций из всех Uberbock'ов всех дампов. Другой вариант поиска необходимого Uberblock'а - найти его по значению в дампе (253277 = 03DD5Dh).

    Примечание.
    Данный скрипт будет работать только на пулах созданных на узлах с big-endian архитектурой (x86, etc). Для little-endian архитектур необходимо в функции преобразования массива в число убрать цикл, инвертирующий массив.

    Примечание.
    На платформе i386, функция преобразования массива в число, при больших номерах транзакций, может работать с ошибками. Это вызвано тем, что для представления номера транзакции используется 64-битное число, а expr(1) работает со стандартными типами и может произойти целочисленное переполнение. Для 64-битной платформы (AMD64) такого ограничения быть не должно (но не проверялось).

    Листинг 2.6.1. Скрипт извлекающий номера транзакций Uberblock'ов
    #!/bin/sh
    
    DISKS="ad2 ad4 ad6"
    LABELS="0 1 2 3"
    
    FIELD_OFF=16
    FIELD_LEN=8
    
    arr2int()
    {
      arr=""
      res=0
    
      # Invert octet order
      for oct in $1; do
        arr="$oct $arr"
      done
    
      # Convert
      for oct in $arr; do
        oct=`printf "%d" 0x$oct`
        res=`expr -e $res \* 256 + $oct`
      done
    
      echo $res
    }
    
    fin=`expr 256 \* 1024`
    prev=""
    for DISK in $DISKS; do
      for L in $LABELS; do
        fdump="$DISK-label$L.dump"
        # First block pos
        off=`expr 128 \* 1024 + $FIELD_OFF`
        n=0
        while [ $off -lt $fin ]; do
          # Get octets array
          str=`od -t xC -A n -v -j $off -N $FIELD_LEN $fdump`
          str=`echo $str | sed 's/^ *\([^ ].*[^ ]\) *$/\1/'`
          # Convert to integer
          txg=`arr2int "$str"`
          printf "txg %10u disk %s label %s n %3u\n" $txg $DISK $L $n
          off=`expr $off + 1024`
          n=`expr $n + 1`
        done
      done
    done
    


    После запуска скрипта и перенаправления вывода в файл, получил список из 1536 записей (3 диска с 4 метками по 128 блоков в каждой). Далее сортируем его по номеру транзакции и определяем наибольший.

    Листинг 2.6.2. Поиск Uberblock'а с наибольшим номером
    ~# ./extract-ub-txg.sh > txg.lst
    ~# sort txg.lst | tail -n 10
    txg     253276 disk ad6 label 2 n  92
    txg     253276 disk ad6 label 3 n  92
    txg     253277 disk ad2 label 0 n  93
    txg     253277 disk ad2 label 1 n  93
    txg     253277 disk ad2 label 2 n  93
    txg     253277 disk ad2 label 3 n  93
    txg     253277 disk ad6 label 0 n  93
    txg     253277 disk ad6 label 1 n  93
    txg     253277 disk ad6 label 2 n  93
    txg     253277 disk ad6 label 3 n  93
    


    Ага. Транзакция 253277 есть только на ad2 и ad4 видимо на ней ad4 и стало плохо. Теперь определим, на каких дисках есть запись о предыдущей транзакции и с каким номером были записаны метки на дисках.

    Листинг 2.6.3. Определение номеров транзакций меток
    ~# zdb -l /dev/ad2 | grep "txg"
        txg=253277
        txg=253277
        txg=253277
        txg=253277
    ~# zdb -l /dev/ad4 | grep "txg"
        txg=247242
        txg=247242
        txg=247242
        txg=247242
    ~# zdb -l /dev/ad6 | grep "txg"
        txg=253277
        txg=253277
        txg=253277
        txg=253277
    


    Листинг 2.6.4. Поиск Uberblock'ов последней и предпоследней транзакций
    ~# grep "25327[67]" txg.lst | sort
    txg     253276 disk ad2 label 0 n  92
    txg     253276 disk ad2 label 1 n  92
    txg     253276 disk ad2 label 2 n  92
    txg     253276 disk ad2 label 3 n  92
    txg     253276 disk ad4 label 0 n  92
    txg     253276 disk ad4 label 1 n  92
    txg     253276 disk ad4 label 2 n  92
    txg     253276 disk ad4 label 3 n  92
    txg     253276 disk ad6 label 0 n  92
    txg     253276 disk ad6 label 1 n  92
    txg     253276 disk ad6 label 2 n  92
    txg     253276 disk ad6 label 3 n  92
    txg     253277 disk ad2 label 0 n  93
    txg     253277 disk ad2 label 1 n  93
    txg     253277 disk ad2 label 2 n  93
    txg     253277 disk ad2 label 3 n  93
    txg     253277 disk ad6 label 0 n  93
    txg     253277 disk ad6 label 1 n  93
    txg     253277 disk ad6 label 2 n  93
    txg     253277 disk ad6 label 3 n  93
    


    Итак, текущий активный Uberblock располагается в 93 позиции массива Uberblock'ов на дисках ad2 и ad6. Uberblock предыдущей транзакции расположен в 92 позиции на всех дисках. Остаётся рассчитать смещение в дампе 93 позиции массива: 128 + 93 = 221 (Кб). Проверим расчёт, найдя блок по номеру транзакции: 253277 = 03dd5dh, с учётом порядка байт, нужно найти последовательность: 5d dd 03 00.

    Листинг 2.6.5. Поиск Uberblock'а по номеру транзакции
    ~# od -t xC -A x ad2-label0.dump | grep -B 1 "5d  dd  03  00" | head -n 2
    0037400    0c  b1  ba  00  00  00  00  00  0e  00  00  00  00  00  00  00
    0037410    5d  dd  03  00  00  00  00  00  71  78  02  5c  2e  cc  05  2d
    


    Искомая последовательность найдена по смещению 037410h, блок начинается по смещению 037400h, т.к. поле txg расположено по смещению 10h = 16 байт от начала блока. Переведём в килобайты: 037400h / 400h = ddh = 221 - предыдущий расчёт смещения был сделан верно. Остаётся затереть текущие активные блоки и записать метки назад на диск. Но перед этим стоит сохранить оригинальные метки.

    Листинг 2.6.6. Удаление Uberblock'ов
    ~# mkdir orig
    ~# cp ad*.dump ./orig/
    ~# dd if=/dev/zero of=ad2-label0.dump bs=1024 count=1 seek=221 conv=notrunc
    1+0 records in
    1+0 records out
    1024 bytes transferred in 0.000078 secs (13134457 bytes/sec)
    ~# dd if=/dev/zero of=ad2-label1.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    ~# dd if=/dev/zero of=ad2-label2.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    ~# dd if=/dev/zero of=ad2-label3.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    ~# dd if=/dev/zero of=ad6-label0.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    ~# dd if=/dev/zero of=ad6-label1.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    ~# dd if=/dev/zero of=ad6-label2.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    ~# dd if=/dev/zero of=ad6-label3.dump bs=1024 count=1 seek=221 conv=notrunc
    ...
    


    Было бы неплохо проверить, те ли блоки были затёрты.

    Листинг 2.6.7. Проверка содержимого блоков
    ~# od -t xC -A x -v ad2-label0.dump | grep -A 1 "^0037410"
    0037410    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
    0037420    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
    


    Так, блоки затёрты - остаётся вернуть метки на диск.

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

    Для записи меток обратно на диски я немного модифицировал первоначальный скрипт и запустил его.

    Листинг 2.6.8. Скрипт записи меток на диски
    #!/bin/sh
    
    L0_OFF=0
    L1_OFF=256
    L2_OFF=1465137920
    L3_OFF=1465138176
    
    DISKS="ad2 ad4 ad6"
    
    echo "Script disabled. Exit."
    exit
    
    for DISK in $DISKS; do
      echo "Write labels to: $DISK"
      l=0
      for OFF in $L0_OFF $L1_OFF $L2_OFF $L3_OFF; do
        fdump="$DISK-label$l.dump"
        echo "  Label: $l (in: $fdump, offset: $OFF)"
    
        # Writing
        dd if="$fdump" of="/dev/$DISK" bs=1024 count=256 seek=$OFF 2> /dev/null
    
        l=`expr $l + 1`
      done
    done
    


    Скрестив пальцы, импортирую пул в режиме только для чтения.

    Листинг 2.6.9. Импорт пула в режиме только чтение
    ~# zpool import -o ro storage
    


    И-и-и-и, о чудо! Пул импортировался и чувствует себя нормально.

    Листинг 2.6.10. Состояние пула после импорта
    ~# zpool status
      pool: storage
     state: ONLINE
    status: The pool is formatted using an older on-disk format.  The pool can
            still be used, but some features are unavailable.
    action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the
            pool will no longer be accessible on older software versions.
     scrub: resilver completed after 0h0m with 0 errors on Wed Dec 28 16:08:41 2010
    config:
    
            NAME        STATE     READ WRITE CKSUM
            storage     ONLINE       0     0     0
              raidz1    ONLINE       0     0     0
                ad2     ONLINE       0     0     0
                ad4     ONLINE       0     0     0  23K resilvered
                ad6     ONLINE       0     0     0
    
    errors: No known data errors
    


    Быстренько достав винт подходящего объема, запустил полное копирование всех данных с пула на него, т.к. продолжать работать с пулом, побывавшим в состоянии "FAULTED" - не наш метод. И вот пока бегут в обратную сторону часы, оставшиеся до завершения копирования я и решил записать эту небольшую историю.

    Год спустя

    Ещё весной задал на форуме вопрос о поддержке "отмотки" транзакций. И был направлен тов. Anon Y Mous на путь истинный, т.е. в последние (на тот момент) правки HEAD-ветки. Немного покопавшись в репозитории, нашёл нужную правку[3], в которой была добавлена поддержка той самой "отмотки" транзакций. Но это всё предисловие.

    После обновления, в правке за номером 219089 [3], ZFS до версии 28, в zpool(8) появилась возможность откатываться на несколько транзакций назад при передаче параметра -F. Так что описанный в статье приём восстановления стал обычной рутинной задачей. За подробностями по ссылке на правку или в подсказку, выводимую zpool(8).

    Мораль

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

    Список литературы

    1. Need Help Invalidating Uberblock // http://mail.opensolaris.org/pipermail/zfs-discuss/2008-December/024427.html
    2. ZFS On-Disk Specification // http://opensolaris.org/os/community/zfs/docs/ondiskformat0822.pdf
    3. FreeBSD repo revision 219089 // http://svnweb.freebsd.org/base?view=revision&revision=219089



    Ссылка на обсуждение: http://forum.lissyara.su/viewtopic.php?f=14&t=30532.

    размещено: 2011-02-04,
    последнее обновление: 2012-02-02,
    автор: BlackCat

    оценить статью:

    kazak, 2011-01-22 в 12:15:07

    Статья хорошая, а мог бы ты описать сценарий действий штатными средствами?

    BlackCat, 2011-01-23 в 21:53:26

    Штатными средствами ZFS сама себя восстанавливает без внешнего вмешательства. Если только диск не вышел из строя. В этом случае меняем диск.

    Black Cat, 2011-02-04 в 13:25:17

    Слуяайно у нас одинаковые ники
    Статья, мега
    Проделана серьезнаю работа

    Очень было интересно почитатать

    Аноним, 2011-02-04 в 14:25:18

    Вот и зачем тащить весь этот Ынтырпрайз, к тому же ещё нестабильный, в сохо-сектор? Не понимаю.

    BlackCat, 2011-02-04 в 15:07:11

    Тов. Аноним есть такое подозрение, что вы меня не совсем правильно поняли. Сама статейка - это доказательство (prof of concept) возможности восстановления руками. О конкретных показателях надёжности я даже не пытался сделать никаких выводов - это сложная тема, требующая большого объёма исследований и выходящая за рамки моей компетенции. В данном конкретном случае ZFS начала сбоить из-за глючного железа и сбоя питания, а не ошибок в коде реализации и просчётов главного архитектора ФС. После замены диска и пересоздания пула и до настоящего момента - ни одной ошибки, но это то же не показатель.
    Если же говорить о теоритической возможности выхода из строя, то да, она существует. Но с таким же успехом можно раскритиковать устройство вселенной, т.к. существует теоритическая возможность прекращения её существования.
    А если серьёзно. Есть желание убедить сообщество в том, что время ZFS ещё не пришло или ей не место в том или ином классе систем хранения, интересно самому разобраться - создайте тему на форуме, привидите аргументы, там и подискутируем.

    GrossHo, 2011-02-04 в 16:36:01

    После прочтения я стал чувствовать свою кожу более сухой и шелковистой, что стало дополнительным плюсом чтобы использовать ZFS на своих серверах. Есть одно замечание не касающееся проделанной работы, а одного малоинтересного факта: для x86 и amd64 характерен Little Endian, тогда как для Sparc - Big Endian. Еще раз спасибо за интересную статью.

    BAZ Megodriver, 2011-02-04 в 18:34:09

    Очень правильная мораль....
    Она всегда верна.

    MarvinFS, 2011-02-04 в 19:04:54

    Мега респект!!!! просто душа поёт за наших отечественных специалистов которые еще могут победить "систему"! Спасибо!

    Hubbitus, 2011-02-04 в 19:36:51

    Мега-статья!

    Еще бы на основе наработок и опыта написать бы какую-то утилитку для более-менее автоматического использования другими. Было бы вообще супер.

    Morty, 2011-02-07 в 10:33:58

    статья отличная !! понравилось
    Автору респект

    Bx, 2011-02-25 в 21:18:36

    А чем плохи номера транзакций последних, выдаваемых "zdb -l"? Чисто теоретически - мог бы сработать откат на меньшую из, вероятно.

    sage444, 2011-03-04 в 9:43:20

    Где-то в рассылке встречал упоминания о чем-то похожем, но тут все очень детально и понятно.
    автору респект!

    BlackCat, 2011-03-11 в 23:30:07

    Bx, zdb(8) с параметром -l выдаёт номер транзакции в которой была записана метка (label), а не номер последней транзакции, произведённой в пуле.
    Насчёт отката к предыдущей транзакции: так о нём и шла речь.

    winterheart, 2011-03-14 в 8:27:09

    Статья хорошая, но IMHO, ситуация - суета вокруг рояля. Надо было делать дампы/бекапы изначально. Вспоминаем старую поговорку сисадминов.

    playnet, 2011-04-05 в 0:46:04

    Выпал 1 диск из 5 рейда (по сути) и смерть всех данных? Как-то оно вообще ненадежно тогда. Смерть при потере 1 диска допустима исключительно для страйпа!
    Остальные диски были нормальные или тоже с бэдами?

    BlackCat, 2011-04-05 в 0:51:31

    playnet, обратите внимание на мой коментарий от 2011-02-04.

    Мфынф, 2011-07-09 в 8:53:20

    Ахуеть , дайте две.
    Тока нах он такое нужен zfs если один диск выпал и куку.

    BlackCat, 2011-11-23 в 22:55:57

    Обновил статью, добавив раздел "Год спустя". В zpool(8) добавили параметр, позволяющий выполнять откат на несколько транзакций назад.

    Пострадавший, 2011-11-25 в 17:39:59

    Вы бы оставили свои правки для spa.c :)

    BlackCat, 2011-11-26 в 1:44:21

    Какие?!! Если вы имеете ввиду отладочный вывод - то в нём нет ничего необычного: перед ключевыми точками ветвления ставиться функция отладочного вывода, через которую выводим значения параметров участвующих в условии перехода.

    BlackCat, 2012-02-02 в 12:19:27

    Наконец-то понял, какую ошибку имел ввиду GrossHo: были неправильно указаны названия для порядка байт. Правильные названия, как уже было указано: для x86 и amd64 характерен Little Endian, тогда как для Sparc - Big Endian.
    GrossHo, спасибо.

    chpoqxie, 2012-03-04 в 22:58:17

    Я в свое время, когда убедился в бесплодности попыткой поднять упавший raidz на четырех винтах под фряхой, загрузился с инсталл-цд солярки x86, и она прекрасно подцепила пул, пофиксила его, и после этого фряха нормально с ним общается.

    имхо, не стоит юзать zfs под fbsd для критичной инфы. по крайней мере, полгода назад точно не стоило. а в конце 2010-начале 2011 - ууу. автор - камикадзе.

    Karharot, 2013-09-01 в 0:13:48

    http://www.linux.org.ru/forum/general/9530626


    Оставьте свой комментарий:
    Ваше имя:   *
    e-mail:  
    жирный
    наклонный
    подчёркнутый
    ссылка
    цвет
    Нынешний год:   *
     


  • Хостинг HOST-FOOD

    2014-07-27, lissyara
    gmirror

    Удалённое создание софтверного зеркала средствами gmirror, на диске разбитом с использованием gpart. Использование меток дисков для монтирования разделов.
    2013-08-20, zentarim
    Scan+Print server FreeBSD 9

    Настройка сервера печати и сервера сканирования под управлением операционной системы FreebSD 9 для МФУ Canon PIXMA MP540
    2011-11-20, BlackCat
    Разъём на WiFi-карту

    Делаем съёмной несъёмную антену на WiFi-карте путём установки ВЧ-разъёма
    2011-09-14, manefesto
    Настройка git+gitosis

    Настройка системы контроля версия исходного кода в связке git+gitosis+ssh
    2011-08-14, zentarim
    Wi-FI роутер + DHCP + DNS

    Настройка Wi-Fi роутера на Freebsd 8 + DNS сервер + DHCP сервер: чтобы Wi-Fi клиенты были в одной подсети с проводными, проводные и беспроводные клиенты получали адреса автоматически по DHCP, кэширующ
    2011-06-15, -ZG-
    Охранная система на FreeBSD+LPT

    В этой статье описана попытка реализации простой охранной системы на базе FreeBSD с подключением к ней охранных устройтсв на LPT порт и видеорегистрацией.
    2011-03-13, terminus
    ng_nat

    Описание работы ng_nat, практическое использование, достоинства и недостатки в сравнении с ipfw nat
    2011-02-20, Капитан
    Nagios+Digitemp

    Статья описывает создание системы оповещения о превышении температуры в специальных помещениях на основе Nagios с использованием программы Digitemp.
    2011-02-17, Le1
    Zyxel Configuration

    Скрипт для массового изменения конфига свичей Zyxel. Берет из файла iplist список ip-шек, заходит последовательно на каждый и выполняет комманды из файла commands, записывая происходящее в лог файл.
    2011-02-16, fox
    hast carp zfs ucarp cluster

    HAST (Highly Available Storage), CARP, UCARP, ZFS, Cluster настройка и одаптация плюс личные размышления…
    2011-02-04, BlackCat
    Восстановление ZFS

    История о том, как был восстановлен развалившийся RAIDZ ZFS-пул (перешедший в FAULTED) с помощью скотча и подручных средств. Или о том, какие приключения ожидают тех, кто не делает резервных копий.
    2011-02-03, Капитан
    1-Wire

    Статья описывает самостоятельное изготовление контроллера DS9097 для съёма показаний с датчиков температуры DS1820 с помощью программы Digitemp.
    2011-01-28, Капитан
    Температура в серверной

    Статья описывает построение системы наблюдения за температурой в помещении серверной с использованием программы Digitemp и выводом графиков в MRTG
    2011-01-21, m4rkell
    Syslog server

    Как то буквально на днях, у нас завалилось, что то в еве) или не в еве не суть. Суть в том, что когда захотели снять логи с хостов esx обнаружили, что хранят эти негодяи логии только за последнии сутк
    2011-01-07, lissyara
    Canon/gphotofs

    Монтирование цифровых фотоаппаратов Canon (PTP) как файловой системы, автоматизация этого процесса через события devd и внешние скрипты.
    2010-12-13, Al
    IPSec

    Описание принципов работы IPSEC и способов аутентификации.
    2010-12-07, manefesto
    FreeBSD on flash

    Было принято решении переехать на USB Flash и установить минимальный джентельменский набор для работы своего роутера. Делаем =)
    2010-12-05, Fomalhaut
    root ZFS, GPT

    Инструкция по установке FreeBSD с использованием в качестве таблицы разделов GPT и в качестве основной файловой системы - ZFS
    2010-09-05, Cancer
    Настройка аудиоплеера на ximp3

    Цели: Простенький аудиоплеер, для того что бы тетя продавец в магазине утром пришла нажала на кнопку Power и заиграла в зале музыка, так же был доступ по сети, общая шара куда можно заливать музыку, к
    2010-08-31, Cancer
    Установка и настройка OpenVPN

    На днях появилась задача - объединить головной офис и 3 филиала в одну сеть через интернет посредством OpenVPN, чтобы люди могли подключаться через RDP к базам 1С на серверах.
    2010-08-25, manefesto
    freebsd lvm

    Использование linux_lvm для работы с LVM разделами из-под FreeBSD. Проблемы которые возники при монтирование lvm раздела
    2010-04-30, gonzo111
    proftpd file auth&quota

    Proftpd - квоты и авторизация из файлов, без использования базы данных и/или системных пользователей
    2010-04-22, lissyara
    tw_cli

    Пошаговая инструкция по восстановлению RAID на контроллере 3ware, из которого выпал один диск. Настройка мониторинга состояния рейда и отчётов о его состоянии на email.
    2010-04-14, fox
    MySQL Master+Master

    MySQL (Master Master) and (Master Slave) Как настроить репликацию…
    2010-03-09, terminus
    DNS zones

    Краткий ликбез про управление DNS зонами. Примеры проведения делегирования прямых и обратных DNS зон.
    2010-03-09, aspera
    Squid+AD (group access)

    Настройка прокси сервера SQUID с автроризацией пользователей в AD. Разделение пользователей на группы
    2010-03-02, BlackCat
    Шлюз: Часть 4

    Настройка дополнительных сервисов: синхронизация времени (OpenNTPD), клиент DynDNS.org.
    2010-03-01, BlackCat
    Шлюз: Часть 3

    Настройка DHCP и DNS серверов для работы внутри частной сети, c поддержкой внутренних (частных зон) DNS, а так же интеграция DHCP и DNS сервисов.
    2010-03-01, BlackCat
    Шлюз: Часть 2

    Конфигурация МСЭ pf для проброса портов с изменением порта назначения и без, а так же поддержки активного режима FTP и ограничения максимального размера сегмента
    2010-03-01, BlackCat
    Шлюз: Часть 1

    Быстрая настройка шлюза/маршрутизатора с установлением PPPoE-соединения, поддержкой NAT и DNS-forwarding.
    2010-02-23, Morty
    darkstat

    Простая считалка траффика, со встроенным веб-сервером. Очень маленькая, может делать отчеты трафика по хостам, портам, протоколам, а также строить графики
    2010-01-23, gonzo111
    squid+sams+sqstat

    Пилим squid и sams - примеры конфигов с объяснениями. Установка SqStat.
    2009-12-19, schizoid
    mpd5 + radius + ng_car + Abills

    Настройка pppoe-сервера с биллинговой системой Abills и шейпером ng_car
    2009-11-16, lissyara
    UFS->ZFS

    Удалённая миграция с UFS на ZFS. Загрузка с раздела zfs. Настройка для работы с малым количеством памяти под архитектурой i386.
    2009-11-13, gx_ua
    fusefs-ntfs

    Установка, настройка и использование fusefs-ntfs, драйвер NTFS, предназанченного для монтирования NTFS разделов под FreeBSD
    2009-11-12, Morty
    LiveCD

    Создание собственного LiveCD с необходимыми вам изменениями, автоматизирование данного процесса, а так же вариант скоростной сборки СД.
    2009-09-27, lissyara
    Samba как PDC

    Контроллер домена - аналог M$ NT4 домена под самбой, без использования LDAP и прочей хиромантии. Просто и быстро =)
    2009-08-30, terminus
    ipfw nat

    Подробное руководство по ipfw nat, сложные случаи конфигурации.
    2009-08-24, levantuev
    HotSpot

    Установка Hotspot системы в общественное заведение.
    2009-08-18, lissyara
    diskless

    Создание бездисковых терминалов под управлением FreeBSD - с загрузкой по сети. Используются для старта rdesktop и подключения к виндовому серверу терминалов.
    2009-07-29, BAV_Lug
    Видеонаблюдение

    Настройка бюджетного варианта видеонаблюдения на удаленном объекте
    2009-07-22, Cancer
    OpenLDAP адресная книга

    Настройка и создание адресной книги на базе OpenLDAP + phpLDAPadmin
    2009-06-30, SergeySL
    AimSniff

    Руководство по созданию системы мониторинга ICQ-переписки на базе AimSniff, использующей базу данных MySQL для хранения и Web-интерфейс WAS (Web Aim Sniff) для просмотра перехваченных сообщений
    2009-06-25, atrium
    Управление правами доступа

    Полномочия пользователей и файлов, принадлежащих им, формирует концепцию ОС UNIX.
    2009-06-16, DNK
    Exim+PgSQL

    Установка почтовой системы exim+pgsql на FreeBSD 7.1
    2009-05-30, mvalery
    HDD(mbr) -> HDD(gpt)

    Как разбить диск размером более 2TB на разделы, сделать загрузочным, а затем перенести на него информацию с рабочей системы — донора.
    2009-05-22, Cancer
    SendXMPP

    Отправка сообщений на Джаббер сервер по средствам SendXMPP
    2009-05-11, Raven2000
    Network UPS Tools

    Network UPS Tools представляет собой набор программ, которые обеспечивают общий интерфейс для мониторинга и администрирование UPS оборудования.
    2009-04-29, m0ps
    IPSEC over GRE with RIP

    Пример IPSEC over GRE и динамическим роутингом (RIP), с ADSL в качестве последней мили на оборудовании Cisco.
    2009-04-24, WhiteBear777
    qemu network

    Появилась необходимость поставить на БСД эмулятор(qemu) и настроить в качестве гостевой ОС Windows XP, предоставив ей выход в локалку и в сеть internet...
    2009-04-22, vp
    freebsd + huawei 162 gsm modem

    В статье описывается простой способ подключения модема huawei 162 к freebsd + первичная настройка smstools
    2009-04-12, mvalery
    Мониторинг RAID

    Мониторинг из командной строки RAID компаний AMCC 3ware, HighPoint, Dell (Perc 5/i и PERC 6/i) и LSI (MegaRAID SAS 8408E и SAS1078)
    2009-04-09, texnotronic
    RAID1 via LAN

    Функциональности DRBD во FreeBSD можно добиться примонтировав блочное устройство по сети при помощи GEOM Gate (ggate) и добавив его в зеркало с локальным диском средствами gmirror.
    2009-04-03, Raven2000
    Оптимизация хоста для CMS

    В последнее время на старый и не очень быстрый ПК (Celeron 800 RAM 256) мною было навешано с десяток сайтов и некоторые были из серии тяжелых CMS. И так нам дано FreeBSD 7.1 и ~10 сайтов/CMS.
    2009-04-01, atrium
    VSFTPD + AD && MySQL

    Настройка самого безопасного сервера FTP - vsftpd.
    2009-03-31, Dron
    Peoplenet + C-motech (3G)

    Описание подключения к сети Peoplenet посредством 3G модема С-motech CCu-650U на FreeBSD
    2009-03-25, lissyara
    mod_auth_external

    mod_auth_external - авторизация пользователей в apache c помощью внешней программы - например, системных пользователей.
    2009-03-24, gx_ua
    Lightsquid

    Частично lightsquid может заменить sams: быстрая и простая инсталляция, быстрый парсер, cgi скрипт для динамической генерации отчета, нет привязки к БД, различные графические отчеты, мультиязычный инт
    2009-03-18, LHC
    Установка Zabbix-1.6

    Установка и первоначальная настройка системы мониторинга Zabbix (версия 1.6)
    2009-03-16, Cancer
    Принт-Сервер Samba+LPD & AD

    Простейшая настройка Принт-Сервера на FreeBSD используя Samba+LPD & AD
    2009-03-04, Mad_caterpillar
    ipsec_vpnc

    Настройка VPN IPSec концентратора на FreeBSD 6.2 для клиента cisco с использованием ipsec-tools и авторизацией в активной директории
    2009-02-18, Andy
    Free-SA

    Программа анализирует log файлы Squid'а и формирует по ним отчет.
    2009-02-02, Cancer
    Openfire Jabber Server

    Установка Jabber сервера на примере Openfire
    2009-01-28, Cancer
    mpd5 + сжатие и шифрование

    Установка VPN сервера mpd5 + сжатие и шифрование
    2009-01-26, vp
    freebsd + webcamera

    Подключение и настройка вебмкамеры для работы с freebsd на примере Logitech QCam STX
    2009-01-10, Grishun_U_S
    конфиг для офисов

    В статье разбирается конфиг для офиса, пользователи которого имеют строгие ограничения по портам. Заворачиваем www трафик на транспарентный прокси, а остальное NAT'им. Эффективно делим канал интернет
    2008-12-27, Storoge
    sftp+chroot

    Возникла необходимость дать возможность нескольким пользователям заливать на сервер контент для своих сайтов через sftp, чтобы при этом не страдала безопасность.
    2008-12-13, Morty
    PurefFTPd

    Администрирование pureftpd-сервера с помощью вэб интерфейса Usermanager
    подписка

        вверх      
    Статистика сайта
    Сейчас на сайте находится: 14 чел.
    За последние 30 мин было: 51 человек
    За сегодня было
    9393 показов,
    621 уникальных IP
     

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

    © lissyara 2006-10-24 08:47 MSK

    Время генерации страницы 0.0602 секунд
    Из них PHP: 53%; SQL: 47%; Число SQL-запросов: 77 шт.
    Исходный размер: 213715; Сжатая: 40338