Восстановление открытых файлов но удаленных c файловой системы linux

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

    Предыстория


    Зашел человек на канал посвященный debian в jabber и сказал что взломали его jabber-bot и выполнили команду:
    $ rm -rf /*

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

    Восстанавливаем файл


    Первым делом нам нужно убедиться что у нас стоит приложение lsof и примонтирован procfs в /proc.
    В этой заметке я буду считать что в системе где будут восстанавливаться открытые файлы все нужные приложения стоят, root доступ есть, всё примонтировано как нужно.

    Первым делом нам нужно найти открытый файл с помощью программы lsof:
    $ sudo lsof | grep filename

    Пример:
    $ sudo lsof | grep /home/anton/.xsession-errors
    kwin 2031 4002 anton 2w REG 253,3 4486557 1835028 /home/anton/.xsession-errors

    Нас интересуют вот эти значения:
    • Номер процесса (pid)
    • Файловый дескриптор (file descriptor)

    Здесь я выделю жирным то что нужно:
    kwin 2031 4002 anton 2w REG 253,3 4486557 1835028 /home/anton/.xsession-errors

    Дальше восстанавливаем его (вы можете также его сохранить в другом месте):
    $ sudo cp /proc/2031/fd/2 /home/anton/.xsession-error

    На этом всё, так можно восстановить открытый файл, но который по какой-то причине был удален.

    UPD1: Меня спросили как найти и восстановить все открытые файлы конкретным приложением.
    Предположим мы знаем 1 файл который нужно восстановить, мы его нашли с помощью
    $ sudo lsof | grep /home/anton/.xsession-errors
    kwin 2031 anton 2w REG 253,3 4486557 1835028 /home/anton/.xsession-errors

    Мы знаем что 2031 — это pid процесса который держит ваш файл. Нам нужно найти все файлы которые держать открытыми данный процесс:
    $ sudo lsof -p 2031

    Мы видим все открытые приложения этим процессом, нам осталось только отобрать удаленные:
    $ sudo lsof -p 2031 | grep deleted

    После чего просто восстанавливаем все файлы как описано выше.

    UPD2: Почему я использую grep для поиска файлов вместо параметра, который работает быстрей?
    Я использую grep так как там видно удален файл или нет, я считаю это более удобным (ИМХО)

    UPD3: Также можно посмотреть все открытые файлы процесса через комманду ls, пометки deleted будут, пример:
    $ ls -lia /proc/2031/fd/
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 32

      –9
      Проверили бы через текстовый редактор написанный материал на наличие хотя бы орфографических ошибок. Материал хороший, а читать невозможно.
        +2
        Прошу прощение, в системе что-то spell-ru не хочет работать ни в одной проге, то что нашел — поправил, если найдете что-то пишите личное сообщение, исправлю
        • UFO just landed and posted this here
            +6
            Поставил проверку правописания, исправил все найденные ошибки
            +5
            Написали бы ещё поподробнее — что вообще происходит с открытым файлом при его удалении, где (на диске или в памяти) всё это время хранится копия удалённого файла, работает ли такой метод с большими файлами?
              +4
              Файл лежит где лежал, пока он открыт хоть одним процессом. Как только все процессы закроют файл или завершатся, место на диске помечается как свободное и может быть перезаписано другим файлом.
                +1
                При открытии файла увеличивается счётчик жёстких ссылок, при закрытии — уменьшается. Если счётчик = 0, то место, занимавшееся файло, считается пустым.
                Так что, возможно, прокатит метод не только «cp /proc/pid/fd/n blah», а и «ln ....» (а может и нет, ведь точки монтирования у /proc и остального разные).
                +6
                Вместо grep правильнее передавать путь самому lsof:
                datacompboy@nuuzerpogodible:~$ tail 123 -f &
                123
                datacompboy@nuuzerpogodible:~$ lsof /home/datacompboy/123 
                COMMAND   PID        USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
                tail    29434 datacompboy    3r   REG    8,5        4 1765588 /home/datacompboy/123
                datacompboy@nuuzerpogodible:~$ lsof -p 29434
                COMMAND   PID        USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
                tail    29434 datacompboy  cwd    DIR    8,5    14400    4521 /home/datacompboy
                tail    29434 datacompboy  rtd    DIR    8,5     1008       2 /
                tail    29434 datacompboy  txt    REG    8,5    64232  733586 /usr/bin/tail
                tail    29434 datacompboy  mem    REG    8,5  2855040 1245149 /usr/lib/locale/locale-archive
                tail    29434 datacompboy  mem    REG    8,5  1742520 1463374 /lib/x86_64-linux-gnu/libc-2.17.so
                tail    29434 datacompboy  mem    REG    8,5   145160 1463324 /lib/x86_64-linux-gnu/ld-2.17.so
                tail    29434 datacompboy    0u   CHR  136,0      0t0       3 /dev/pts/0
                tail    29434 datacompboy    1u   CHR  136,0      0t0       3 /dev/pts/0
                tail    29434 datacompboy    2u   CHR  136,0      0t0       3 /dev/pts/0
                tail    29434 datacompboy    3r   REG    8,5        4 1765588 /home/datacompboy/123
                tail    29434 datacompboy    4r  0000    0,9        0    3546 anon_inode
                
                  0
                  Действительно так лучше, исправил
                  +3
                  > Номер открытого файла
                  Понимаю, что слово file descriptor сложновато понятно перевести на русский, но «номер файла» — не корректно. Это вроде и не номер и кроме файла дескриптор может ссылаться, например, на сокет. Таким образом не знающие могут подумать, например, что речь идет про inode.
                  Я бы исправил.
                  Ну и вцелом статья коротковата, конечно. Хорошо бы расписали что к чему поподробнее — про вывод lsof, про freebsd, где /proc, кстати, отсутствует по дефолту. Что такое эти «номера файлов», что такое /proc…
                    0
                    поменять на английский вариант file descriptor?
                      +8
                      Термин «Файловый дескриптор» вполне уже устоялся.
                    0
                    Во FreeBSD нет procfs (в GENERIC) и /proc. И поэтому данный метод восстановления для нее не подходит.

                    P.S. ZFS и снапшоты помогут в восстановлении.
                    • UFO just landed and posted this here
                        0
                        Да, в инете видел что procfs есть, думал что и fd есть, а проверить не мог из-за отсутствия данной ОС под рукой, убрал freebsd из текста
                          0
                          Вы правы, в GENERIC есть:
                          options         PROCFS                  # Process filesystem (requires PSEUDOFS)
                          options         PSEUDOFS                # Pseudo-filesystem framework
                          


                        +5
                        Программы могут один раз прочитать конфиг и не держать его открытым. Так что не всегда поможет.
                          +2
                          Сам исполняемый файл кстати тоже так можно восстановить, из /proc//exe.
                            0
                            /prod/PID/exe, парсер съел
                            0
                            А зачем вообще lsof? cd /proc/pid/fd, ls -lia покажет и список открытых процессом файлов, и позволит прямо оттуда скопировать их по местам.
                              0
                              Наверно, чтобы посмотреть оригинальные названия файлов, что нужно, что нет, что удалено, что нет(чтобы все было в одном месте). То есть просто ради удобства, могу предположить…
                                0
                                Это достигается и через ls:
                                [boris@mbp ~]$ ls -lia /proc/`pgrep tail`/fd
                                [skip]
                                161841737 lr-x------ 1 boris boris 64 Янв  4 20:50 3 -> /home/boris/test0 (deleted)
                                
                                
                                  0
                                  Добавлю этот вариант как буду за компом, спасибо.
                              +2
                              Раз в год стабильно появляется статья человека, открывшего этот способ. Все конечно хорошо, но…
                                0
                                Ну давайте я добавлю «пользы» примером из жизни =)
                                На одном из серверов столкнулись с проблемами свободного места на диске. При этом анализ директорий du'ом не показывал ничего криминального, хотя мы не досчитались под сотню гигов что-ли. Потом выяснилось, что один из долгоиграющих процессов открыл дескриптор большого файла (лога чтоли, не помню, не суть) и писал в него. Запись в каталоге о файле удалили, но пока дескриптор открыт — ОС позволяет спокойно с ним работать. Утилита du при этом покажет «не правильный» размер каталога, с учетом «удаленного» файла.
                                А нашли это как раз с помощью
                                lsof |grep deleted

                                Забавно. Всё не хватает времени поэкспериментировать, как поведут себя различные механизмы квот на дисковое место. Если не правильно учитывать такие вот удаленные файлы, то можно запросто забить диск, не смотря на квоту =) Ни кто не хочет исследовать?
                                  0
                                  Потом выяснилось, что один из долгоиграющих процессов открыл дескриптор большого файла (лога чтоли, не помню, не суть) и писал в него. Запись в каталоге о файле удалили


                                  за такое надо бить больно по рукам )) причем всем: и тем, кто писал код… и тем, кто так удаляет :)
                                    0
                                    Р., я не помню подробностей, но там не специально так сделали. Лог должен был крутиться, но что-то помешало. Поятно, что так нельзя, не первый год замужем =)

                                    ~ $ uptime
                                    13:03:23 up 1016 days,
                                      0
                                      апдейты не ставим, да?! :)
                                      0
                                      какие проблемы? HUP посылаем процессу, он переоткрывает файлы.
                                      вот если он так не делает — вот тогда да, тогда по рукам.
                                        0
                                        о том и речь. писавшим код — за запись «бесконечного» файла. удаляющим — за такие внезапные трюки :)

                                        по уму — есть syslog.
                                    +3
                                    Я примерно так сохраняю видеоролики из онлайна (неважно — ютуб, рутуб, вимео — всё работает).
                                    Просто открываю ролик, жду когда весь скачается — и ищу его fd-шках у процесса /usr/lib/firefox/plugin-container
                                    (можно и lsof-ом, но мне быстрее прямо в mc перелистать все ссылки в папке /proc//fd). Ролик обычно находится в удалённом файле в /tmp (т.е. по окончании просмотра он окончательно канет в небытие). Дальше F5 и отметка галки «разыменовывать ссылки» — и ролик у меня. Можно либо добавить расширение .flv, либо открыть avidemux-ом и пересохранить в «правильный» контейнер.
                                    • UFO just landed and posted this here

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