Как вернуть удалённый конфиг или Никогда не сдавайся!

    image

    Сисадмины делятся на тех, кто не делает бэкапы, и тех кто, их уже делает =)

    Про то как восстанавливать файлы с ext3 / ufs написана не одна статья, так что не буду повторятся и напишу про не самые широко известные способы восстановления конфигов на продакшн сервере.


    Как это произошло?


    Звонок вечером от старого знакомого, работающего ныне в веб студии. На другой стороне полная паника и неопределённость.
    — !"№;%: ААаа! Всё упало нечего не работает. Мне капец, спасай.

    После пятнадцати минут приведения человека в адекватное состояние и выяснения что же всё-таки случилось стало ясно следующее:
    • Их студия не только делает сайты, но и хостит их.
    • Конфиг nginx генерируется скриптом вытаскивая location'ы и rewrite'ы из служебной базы MySQL.
    • База находится на хороших серверах с RAID-1 и master-slave репликацией
    • Бэкапы не делаются, так как «шанс того, что умрут оба винта на обоих серверах равен нулю» (с) Сисадмин этой студии


    По поводу бэкапов


    Что правда, то правда. Действительно, 4 винта умереть одновременно не могут (possible, but statistically unlikely © «Charlie» Eppes, Numb3rs), однако почемуто люди не думают о том, что rm -rf /* выполненный на RAID-1, убьёт инфу и на обоих винтах, так же забывают, что DROP TABLE у нас прореплицируется с одного сервера на другой. Так же, редко кто подозревает о том что в один прекрасный день офис может сгореть из-за пожара / утонуть из-за наводнения / разрушиться из-за землетрясения / уехать вместе с ОБЭПом. В общем off-site бэкапы вообще мало кто делает… А зря, хотя бы раз в месяц сливать всё на флэшку в запароленный .rar и уносить домой можно даже вручную, не особа запариваясь.

    Ни ZFS снапшоты, ни RAID, ни репликация не являются заменой бэкапов. Хоть всё это и понижает шансы потерять данные, и очень хорошо, что это есть, однако, Off-site бэкапы должны быть всегда!

    Ближе к делу


    По Закону Мерфи, то что может случится, просто обязано произойти. Так в этот злополучный вечер из-за ошибки в UPDATE SQL запросе, служебная таблица с данными из которых генерировался конфиг nginx'a была заполнена '', а из-за ошибки в скрипте nginx.conf был перезаписан пустым файлом. Благо nginx штука умная и перед reload'ом конфига проверяет его на правильность, так что применять новый конфиг nginx отказался.

    Как же восстановить перезаписанный конфиг?


    Мой старый знакомый дал мне доступ до фронтенда с nginx.
    Тут всё обыденно: Машинка на FreeBSD, gmirror на два диска и nginx, нечего более.
    Первым делом остановил gmirror, чтобы все мои изменения не перезаписывали файлы на втором винте. Далее начал думать как же восстановить с диска убитый файл, но тут посмотрев на аптайм сервера и вспомнив, что знакомый говорил, мол, конфиг меняется довольно редко, решил попробовать другой метод.

    Посмотрел сколько у нас свапа.
    # swapinfo
    Device 1K-blocks Used Avail Capacity
    /dev/ad4s1b 2063152 94612 1968540 5%

    То, что он в данный момент занят на 5% далеко не значит, что там всего 5% информации, скорее всего там её намного больше =)

    Сохраним его текущее состояние
    # cat /dev/ad4s1b > /usr/SWAP

    И зная какую-нить строку из конфига начнём по ней грепить. Так как большинство людей тюнят, как фряху, так и nginx «по Сысоеву», то в конфиге скорее всего есть строчка «reset_timedout_connection on», что ж, проверим мою удачу и попробуем погрепить по ней:

    # cat /usr/SWAP | grep -a -A10 reset_timedout_connection
    �Lj�Lj��Lj��Lj�Lj�Lj$�Lj0�Lj8�Lj<�LjX�Lj\�Ljd�Ljp�Lj��Lj��Lj��Lj��Lj��Lj�Lj��Lj��Lj��Lj���Lj8�LjP�Ljp�Lj��Lj��Lj��Lj�Lj��LjX�Lj
    ��Lj�Lj�m [Ȉh�LjxȈҰLj@������� �.�`�`���0u�0u2�d�d�Lj�Ȉ<4�@TȈ��Ȉ
    --
    reset_timedout_connection on;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    send_lowat 12000;

    keepalive_timeout 65;

    gzip on;
    gzip_min_length 2048;
    gzip_types text/css text/js text/xml;
    ^C

    и вот, вуаля, кусок конфига, осталось только поиграть со значениями -A и -B, выцепить конфиг целиком и выбрать из вариантов самый новый/небитый (возможно их в свапе будет несколько)

    # cat /usr/SWAP | grep -a -A400 -B12 "reset_timedout_connection on;"

    Всё конфиг у нас в руках. Вроде даж не битый и актуальный. Теперь отпарсив его можно восстановить MySQL таблицу.

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

    Если в swap'e нет, а файл с винта не восстановить


    Так же есть второй, менее предпочтительный вариант восстановления информации в случае если на сервере всё ещё запущен процесс nginx

    Для начала ищем напущенный nginx master
    # ps -auxww | grep nginx
    root 1197 0,0 0,1 13216 2488 ?? Is ср18 0:00,02 nginx: master process /usr/local/sbin/nginx
    www 29484 0,0 2,3 57248 47576 ?? I 7:58 0:00,06 nginx: worker process (nginx)


    Далее деаем его coredump
    # gcore 1197
    А потом ковыряем его как хотим, хоть так
    # cat core.1197 | strings | grep -B10 -A10 reset_timedout_connection
    хоть так
    # cat core.1197 | grep -a -B10 -A10 reset_timedout_connection
    … И ужасаемся от того как же сложно собрать конфиг по кусочкам

    Вывод


    Люди, не будьте Сами Себе Злобными Буратинами, делайте частые хорошо защищённые автоматические бэкапы данных. И помните, что даже из самой глубокой жопы есть как минимум два выхода %)

    Вместо послесловия


    MySQL базу в итоге восстановили. Админ сам того не зная включил --bin-log с самого начала жизни базы (кстати, к тому моменту как я начал востанавливать базу binlog уже занимал 89% /var и через пару месяцев mysql перестал бы запускаться). Благодаря тому, что их никто не удалял, можно было сделать Point-in-Time Recovery

    ПС. Неплохо было бы если б nginx мог по запросу выдавать свой текущий конфиг или diff от текущего и того, что лежит в файле на диске =)
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 36

      0
      Еще можно попытаться поискать старый конфиг на незанятом пространстве винчестера.
        +2
        Добрые люди подсказывали что конфиг обитает еще и в /proc//mem.
          0
          Хабр съел pid между слешами. то есть /proc/pid/mem, где pid — nginx master pid/
            0
            Виртуальная система /proc на FreeBSD необязательна и частенько отсутствует.
            % uname -rsm
            FreeBSD 8.0-BETA3 amd64
            % ls /proc
            total 1
            dr-xr-xr-x   2 root  wheel     2B 10 авг 00:07 ./
            drwxr-xr-x  18 root  wheel    24B 28 авг 17:56 ../
            
              +1
              Да, я так пытался восстановить perl-овый скрипт, который был запущен, а исходник — уничтожен. SQL-запросы из скрипта удалось выложить, и теперь я знаю, что в памяти хранится только байт-код +)
              +2
              следуя духу поста, я бы переформулировал поговорку:
              «Сисадмины делятся на тех, кто делает бэкапы, и тех, кто их ещё не делает»

              (ну и запятые вокруг подчинённых предолжений)
                0
                Да, что-то последнее время часто замечаю, что многие ими пренеборегают. Вот недавно наблюдал, как люди чуть не угробили проект из-за того, что посреди рабочего процесса у них SVN-сервер умер… Ну да, действительно, зачем делать бэкапы СВНа, когда его текущее состояние есть у каждого работника?

                ПС. Поправил, спасибо
                  +3
                  коммент получился в таком контексте, будто svn угробили из-за пренебрежения запятыми :)
                    0
                    grammar nazi устроили диверсию?
                      0
                      не. просто читал коммент в почте.
                        0
                        А я собственно развивал тему «кто убил SVN из-за отсутствия запятых».
                        Потому что я прочитал оригинальный пост в том же ключе.
                  0
                  Сисадмины делятся на тех, кто _ещё_ не делает бэкапы и тех, кто _уже_ делает.
                    0
                    ну да. так лучше.
                    идея была подчеркнуть, что один хрен бэкапы рано или поздно делать придётся.
                    +4
                    Все люди делятся на тех, кто делает резервные копии, и тех, кто будет делать резервные копии.
                    +2
                    Не только сисадмины делятся на эти две категории :-) Многие разработчики не делают бекапов. Недавно мой приятель жаловался, что никак не может найти нужную инфу, на что я ему ответил «когда потеря будет материально ощутима, ты всё организуешь как надо».

                    Беда в том, что люди не ценят результатов своей работы, пока они не уничтожены.
                      +1
                      Да уж. Поэтому я даже завёл себе этакую «песочницу» на гугль-коде, и сваливаю в тот свн всё мало-мальски значимое.
                      Профит двойной: во-первых не потеряется (если, конечно, гугель-код не упадёт намертво, в чём я лично сомневаюсь :)), а во-вторых всё доступно из любого места, где есть интернет.
                      +1
                      Немного ускорит процедуру грепания командочка strings, натравленная на сохранённый файл свопа.
                        0
                        Спасибо. Сам бы никогда не нагуглил если бы такое случилось где-либо.
                        По поводу фич nginx действительно не хватает. Да у большинства приложений не хватает просмотра текущего конфига. Слава богу у postfix и конфиг ядра можно всегда реалтайм посмотреть.
                          +2
                          Умные люди после настройки сервера. Копируют все конфиги на добрую память и на всякий случай. Мало ли где еще они могут пригодиться.
                            0
                            Читайте выше ;)
                            «Конфиг nginx генерируется скриптом вытаскивая location'ы и rewrite'ы из служебной базы MySQL.»
                            В этом случае врятли поможет перетастивание конфига после настройки сервера.
                              0
                              Умные люди хранят конфиги в SVN или другой системе контроля версий :)
                              –1
                              Откуда эта дурная привычка писать cat file | grep [args] pattern, когда можно обойтись одним вызовом grep [args] pattern file?
                                0
                                Потому, что мне так удобнее, так, например, я могу вставить тот же "| strings" между cat и grep.
                                  0
                                  Клево, да. А вот «strings file|grep blah» — явно неудобно. Ну кто бы мог подумать.
                                    0
                                    Ну откуда вы такие умные берётесь? Для справки
                                    «cat file | xxxx | grep blablabla» != «grep balblabla file | xxxx»

                                    Вместо xxxx попробуйте представить sed/awk/tr, впрочем в некоторых случаях и strings
                                      0
                                      Нет преград для патриотов: grep blablabla <
                                        0
                                        Парсер лох.

                                        Нет преград для патриотов: grep pattern < <(strings file)
                                      0
                                      А, всё, Лёша не тормоз. Не так вас прочитал. В любом случае, каждый может делать так как ему удобнее. Это и есть Unix-way.
                                    0
                                    Откуда привычка называть вещи, непонятные лично Вам, «дурными»?
                                      0
                                      А почему это дурная привычка? На производительности не сказывается, а читается имхо легче.
                                      0
                                      Красавчик! Я бы про дамп памяти и корку программы не догадался искать.
                                        +1
                                        Я привык использовать git на папке /etc //usr/local/etc что бы конфиги можно было восстановить и проверить когда и что изменилось! Но это не в коем случае не отменяет бэкапов! Автор прав на 120%
                                          0
                                          Хорошая идея, хотя можно, наверное, найти что-то более легковесное чем vcs'ы.
                                            0
                                            Мы у себя /etc со всех серверов собираем при помощи bontmia
                                          +3
                                          автор — шаман однозначно!
                                          • UFO just landed and posted this here

                                            Only users with full accounts can post comments. Log in, please.