LINUX.ORG.RU

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

Недавно столкнулся с обратной проблемой: удалил ненужный длиннющий файл, а за него кто-то продолжал держаться (fuser и lsof не признались, кто именно) и место не освободилось. umount срабатывал только с ключом -l, что оказалось бесполезным. Место удалось освободить только перезагрузкой.

const86 ★★★★★
()
Ответ на: комментарий от const86

>fuser и lsof не признались, кто именно

Под рутом пускал fuser/lsof?

anonymous
()
Ответ на: комментарий от const86

> а за него кто-то продолжал держаться (fuser и lsof не признались, кто именно)

как это? pid всегда видно, а этому процессу всегда можно сказать kill

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

vadiml ★★★★★
()

ну и что толку от такого восстановления?
в 99% случаев удаляецца файл, когда им никто не пользуеться!
здесь данный пример не спосает :-/

Все ИМХО

Ant0
()

За папки с мамками надо расстреливать на месте без права переписки. А так - прикольненько.

anonymous
()

Переводчик, покажи слово "папка" в оригинальном тексте.

anonymous
()
Ответ на: комментарий от Ant0

> в 99% случаев удаляецца файл, когда им никто не пользуеться!

зато в 1% случаев - независимо от типа файловой системы!

szh ★★★★
()
Ответ на: комментарий от szh

>So it's interesting, but not as general as the title of the article makes it sound.

Аффтара наказать. Название статьи как в дышевой пожелтевшей бу газетенке. =)

Тем не менее, прочитал с интересом. %)

anonymous
()
Ответ на: комментарий от anonymous

>наши - рулят!

Рулят-то они рулят, но уж очень тормоза. Я как-то 300Гиг прошерстить пытался - так и не дождался окончания.

anonymous
()

Отлично. Недавно задавался вопросом о возможности подобного действа.

stassats ★★★★
()
Ответ на: комментарий от const86

> ...fuser и lsof не признались, кто именно

fuser -v часто раскрывает карты, lsof вообще не умеет врать. Проблема бывает, когда fs держит само ядро...

Casus ★★★★★
()
Ответ на: комментарий от Casus

> Проблема бывает, когда fs держит само ядро...

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

Tester ★★★
()

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

Обидно мне, досадно мне... да ладно...

В следующий раз осторожнее будем.

Я когда Линукс первый раз ставил, 6 гигов музыки грохнул за секунду, не успел даже испугаться %-)

ip1981 ☆☆
()
Ответ на: комментарий от los_nikos

> А с какого, собственно, дуру человек полез перемещать музыкальный файл в mc?

Не читайте переводы, они полная херня (как всегда). В оригинале идёт рассуждение о перепутанных rm и mv.

anonymous
()
Ответ на: комментарий от anonymous

> А как у него с файлами с пробелом?

Ты про символ "\" слыхивал вообще? Это только в венде он мамку означает, а в нормальных осях - нечто совсем иное.

anonymous
()

Когда работа идёт в консоли, как правило, никто не держит файл открытым, а выполняет по очереди оперцаии над ним.

Я понял, что надо писать makeфайлы (в кр. случае make скрипты), в тот момент, когда первый раз набрал gcc prog.c -o prog.c.

Davidov ★★★★
()

написать что ли статью "Восстановление удалённых файлов с помощью dump/restore"...

anonymous
()
Ответ на: комментарий от Davidov

> Я понял, что надо писать makeфайлы (в кр. случае make скрипты), в тот момент, когда первый раз набрал gcc prog.c -o prog.c.

Кстати, а есть ли вообще возможность восстановления файла, когда он не удаляется, а что-то другое записывается под тем же именем?

ogion ★★
()

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

geekkoo
()
Ответ на: комментарий от ogion

Я востанавливал несколько раз содержимое текстового исходника с помощью:

grep -C 100 "my precious content" /dev/hda1

mihalych ★★★
()

>Восстановление удалённых файлов с помощью lsof
в статье описано как восстановить случайно удаленный файл с помощью
команды lsof.

А как восстановить случайно удаленный lsof(случайно нажал на кнопку
rm -rf /)?

anonymous
()
Ответ на: комментарий от vadiml

> pid всегда видно, а этому процессу всегда можно сказать kill

Увы, не всегда. Если процесс ушёл в себя по поводу зависшего ввода/вывода, то только reboot.

Obidos ★★★★★
()
Ответ на: комментарий от geekkoo

> От случайного удаления гарантированнно помогают дополнительные хардлинки на файл.

Кстати да. А случайно нет такого софта под линукс, который бы перехватывал удаление (не только командой rm, а и через вызовы ядра), и вместо удаления кидал хардлинк в спец.каталог, который очищается по мере необходимости? Примерно то, что в оффтопике реализовано всякими execsoft undelete.

Annymous
()
Ответ на: комментарий от ero-sennin

А вообще, лучше сразу приучить себя класть всё важное файло в репозиторий, а репозиторий иногда бэкапить на болванки. Гарантия 100%. :)

ero-sennin ★★
()

> в статье описано как восстановить случайно удаленный файл с помощью
> команды lsof.
Только одного не понял... как сикануть (lseek) файл на начало, прежде
чем так "восстанавливать"? Или это по каким-то причинам не требуется?

anonymous
()
Ответ на: комментарий от anonymous

>Только одного не понял... как сикануть (lseek) файл на начало, прежде
>чем так "восстанавливать"? Или это по каким-то причинам не требуется?

Когда открывается файл (в т.ч. с помощью cp) без флажков вроде O_APPEND, он всегда позиционируется на начало.

anonymous
()
Ответ на: комментарий от anonymous

> Когда открывается файл (в т.ч. с помощью cp) без флажков вроде
> O_APPEND, он всегда позиционируется на начало.
ОК, просто не знал, что в /proc/pid/fd обычные символьные ссылки
на файлы. Думал, что там можно читать из дескрипторов самой проги,
и, соответственно, с той позиции, в которой она их оставила, а
там оказались просто ссылки...

anonymous
()
Ответ на: комментарий от anonymous

>ОК, просто не знал, что в /proc/pid/fd обычные символьные ссылки на файлы. Думал, что там можно читать из дескрипторов самой проги, и, соответственно, с той позиции, в которой она их оставила, а там оказались просто ссылки...

При открытии файла из userspace процессу выдается дескриптор (число). Числу в таблице дескрипторов в ядре соответствует struct file, в котором содержится offset. Под struct file живет struct dentry, которая является представлением VFS для записи в директории. Под struct dentry живет struct inode, которая является представлением VFS для конкретного файла. Для открытых жестких ссылок будет разный file, разный dentry, но одна inode. Для одного и того же открытого файла будет разный file, но одинаковая dentry и одинаковая inode. Получить один и тот же file из разных процессов/fd можно только путем fork или передачи структуры посредством специфичного Unix механизма, о котором можно почитать в cmsg(3).

Это, разумеется, в неком приближении.

anonymous
()
Ответ на: комментарий от anonymous

> Получить один и тот же file из разных процессов/fd можно только путем
> fork или
Много чего можно получить только через fork() или... через /proc.
Например mm-контекст процесса можно (было раньше) заmmap()ить из
/proc/pid/mem. Я думал, с дескрипторами та же история. Ошибался.

anonymous
()
Ответ на: комментарий от anonymous

>Много чего можно получить только через fork() или... через /proc.
>Например mm-контекст процесса можно (было раньше) заmmap()ить из
>/proc/pid/mem.


В Linux такую функциональность добавить очень нетривиально (хотя, разумеется, можно), особенно для private mappings, которые нужно тем или иным образом преобразовать в shared, чтобы между mm различных процессов области виртуальной памяти были синхронизированы. Текущая реализация procfs в Linux не позволяет делать mmap на /proc/pid/mem.


В некоторых продвинутых VM (в UVM, если не ошибаюсь) возможно совместное использование несколькими процессами одинаковых каталогов страниц, но в Linux наборы pgd/pte для каждого процесса - свои, а совместное использование памяти между процессами достигается за счет кэшей высокого уровня (для разделяемых отображений файлов - page cache соответствующего file mapping, для анонимной разделяемой памяти - page cache создаваемых на tmpfs ядром файлов).

anonymous
()
Ответ на: комментарий от anonymous

>>наши - рулят!

>Рулят-то они рулят, но уж очень тормоза. Я как-то 300Гиг прошерстить пытался - так и не дождался окончания.

а терабайты не пробовал? надо же хотя бы пытаться соизмерять свои желания с возможностями. данная процедура, надеюсь, нужна очень редко и, только если других вариантов нет и тогда уже "время не имеет значения" (ц) пятый элемент.

опять же, можно в два прохода сделать, если я еще в теме.

anonymous
()
Ответ на: комментарий от Annymous

> Кстати да. А случайно нет такого софта под линукс, который бы перехватывал
> удаление (не только командой rm, а и через вызовы ядра), и вместо удаления
> кидал хардлинк в спец.каталог,

Не совсем то, но слегка похоже:

http://www.netfort.gr.jp/~dancer/software/cowdancer.html.en

Работает через LD_PRELOAD, потому системные вызовы не перехватывает, а только
функци из glibc. И очисткой "по мере необходимости" (а это как?) не занимается.

Dselect ★★★
()
Ответ на: комментарий от Tester

> у меня возникает время от времени такая проблема с лупфайлами
> то есть размонтирую исошку и удаляю - так место не освобождается,

losetup -d /dev/loopN

должен помочь отцу русской демократии.

Dselect ★★★
()
Ответ на: комментарий от anonymous

> В Linux такую функциональность добавить очень нетривиально
А удалить было тривиально? Она там была до недавнего времени.
Пользы от неё, правда, было не много скорее всего... (точнее
ей пользовались многие, но наверное только из лени или из-за
проблем с posix shm в старых glibc)

> особенно для private mappings, которые нужно тем или иным образом
> преобразовать в shared
Нафига? PTE расшарить и всё. Хотя не знаю, как именно там это
было сделано. Факт в том, что работало.

anonymous
()
Ответ на: комментарий от Dselect

> Работает через LD_PRELOAD, потому системные вызовы не перехватывает
Системные вызовы через LD_PRELOAD отлично перехватываются.
По тому, что glibc их всех врапит. Если бы ни это, то как бы
работал, к примеру, aoss?

anonymous
()
Ответ на: комментарий от anonymous

>А удалить было тривиально? Она там была до недавнего времени.

Посмотрел код 2.4.20, 2.6.3, 2.6.8, 2.6.18. Нигде даже намека на подобное нет. Есть mem_open, который ничего не делает, есть mem_read/mem_write/mem_lseek, которые реализуют функциональность read/write/lseek.

Не могли бы вы назвать версию ядра, где вы видели подобное?

>Нафига? PTE расшарить и всё.

Я же выше написал, что в Linux в настоящее время этот подход не используется. И реализовать его, хотя и теоретически возможно, но очень непросто (в настоящее время каталоги страниц для каждого процесса свои - за исключением kernel space, разумеется).

anonymous
()
Ответ на: комментарий от anonymous

На словах "расшарить PTE" - это просто, разумеется. Вы код посмотрите и прикиньте, как вы такую функциональность добавите...

anonymous
()
Ответ на: комментарий от vadiml

> как это? pid всегда видно, а этому процессу всегда можно сказать kill

Не всегда. Проверил: если файл повесить на /dev/loop, то он будет занят, но это никак не обнаружить, если не догадаться посмотреть на этот самый loop. У меня как раз iso'шка была, но я её точно отмонтировал. Возможно, что-то не то сделал и она осталась на loop'е; теперь уже не выяснить...

const86 ★★★★★
()
Ответ на: комментарий от anonymous

[anonymous@lor /]# cat ttt.c
#define _GNU_SOURCE
#define _XOPEN_SOURCE 500

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <alloca.h>

void test_read(unsigned long pid, unsigned long start, unsigned long size) {
    char *s;
    int  fd;

    asprintf(&s, "/proc/%lu/mem", pid);
    fd = open(s, O_RDONLY);
    if (!(fd<0)) {
        char* temp_area = alloca(size);

        printf("test_read: %s (%s)\n", (pread64(fd, temp_area, size, start)==size)?"successful":"failed", strerror(errno));

        close(fd);
    }
    else
        fprintf(stderr, "test_read: error: could not open %s\n", s);

    free(s);
}

void test_mmap(unsigned long pid, unsigned long start, unsigned long size) {
    char *s;
    int  fd;

    asprintf(&s, "/proc/%lu/mem", pid);
    fd = open(s, O_RDONLY);
    if (!(fd<0)) {
        char* temp_area;

        temp_area = mmap(0, size, PROT_READ, MAP_SHARED, fd, start);
        printf("test_mmap: shared %s (%s)\n", (temp_area != MAP_FAILED)?"successful":"failed", strerror(errno));
        if (temp_area != MAP_FAILED) munmap(temp_area, size);

        temp_area = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, start);
        printf("test_mmap: private %s (%s)\n", (temp_area != MAP_FAILED)?"successful":"failed", strerror(errno));
        if (temp_area != MAP_FAILED) munmap(temp_area, size);

        close(fd);
    }
    else
        fprintf(stderr, "test_read: error: could not open %s\n", s);

    free(s);

}

int main(int argc, char* argv[]) {
    unsigned long pid, region_start, region_size;
    int rc;
    char* tail;

    if (argc != 4) {
        fprintf(stderr, "error: usage: %s pid region_start region_size\n", argv[0]);
        return -1;
    }

    pid = strtoul(argv[1], &tail, 10);
    if (*tail) {
        fprintf(stderr, "error: pid is in incorrect format\n");
        return -1;
    }

    region_start = strtoul(argv[2], &tail, 10);
    if (*tail) {
        fprintf(stderr, "error: region_start is in incorrect format\n");
        return -1;
    }

    region_size = strtoul(argv[3], &tail, 10);
    if (*tail) {
        fprintf(stderr, "error: region_size is in incorrect format\n");
        return -1;
    }

    rc = ptrace(PTRACE_ATTACH, pid, 0, 0);
    if (rc<0) {
        fprintf(stderr, "error: could not attach (%s)\n", strerror(errno));
        return -1;
    }

    test_read(pid, region_start, region_size);
    test_mmap(pid, region_start, region_size);

    rc = ptrace(PTRACE_DETACH, pid, 0, 0);
    if (rc<0) {
        fprintf(stderr, "error: could not detach (%s)\n", strerror(errno));
        return -1;
    }

    return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

[anonymous@lor /]# gcc -Wall ttt.c
[anonymous@lor /]# ps
  PID TTY          TIME CMD
14379 pts/10   00:00:01 bash
 6008 pts/10   00:00:00 ps
[anonymous@lor /]# cat /proc/14379/maps
08048000-080f2000 r-xp 00000000 16:07 64894      /bin/bash
080f2000-080f7000 rw-p 000aa000 16:07 64894      /bin/bash
080f7000-0813e000 rw-p 080f7000 00:00 0          [heap]
b7c73000-b7c7c000 r-xp 00000000 16:07 972531     /lib/libnss_files-2.4.90.so
b7c7c000-b7c7d000 r--p 00008000 16:07 972531     /lib/libnss_files-2.4.90.so
b7c7d000-b7c7e000 rw-p 00009000 16:07 972531     /lib/libnss_files-2.4.90.so
b7c7e000-b7e7e000 r--p 00000000 08:01 9612502    /usr/lib/locale/locale-archive
b7e7e000-b7e7f000 rw-p b7e7e000 00:00 0
b7e7f000-b7fb0000 r-xp 00000000 16:07 972504     /lib/libc-2.4.90.so
b7fb0000-b7fb2000 r--p 00131000 16:07 972504     /lib/libc-2.4.90.so
b7fb2000-b7fb3000 rw-p 00133000 16:07 972504     /lib/libc-2.4.90.so
b7fb3000-b7fb6000 rw-p b7fb3000 00:00 0
b7fb6000-b7fb8000 r-xp 00000000 16:07 972671     /lib/libdl-2.4.90.so
b7fb8000-b7fb9000 r--p 00001000 16:07 972671     /lib/libdl-2.4.90.so
b7fb9000-b7fba000 rw-p 00002000 16:07 972671     /lib/libdl-2.4.90.so
b7fba000-b7fbd000 r-xp 00000000 16:07 972605     /lib/libtermcap.so.2.0.8
b7fbd000-b7fbe000 rw-p 00002000 16:07 972605     /lib/libtermcap.so.2.0.8
b7fbe000-b7fbf000 rw-p b7fbe000 00:00 0
b7fdc000-b7fde000 rw-p b7fdc000 00:00 0
b7fde000-b7fe5000 r--s 00000000 08:01 41959290   /usr/lib/gconv/gconv-modules.cache
b7fe5000-b7fe6000 r-xp b7fe5000 00:00 0          [vdso]
b7fe6000-b7fff000 r-xp 00000000 16:07 972489     /lib/ld-2.4.90.so
b7fff000-b8000000 r--p 00018000 16:07 972489     /lib/ld-2.4.90.so
b8000000-b8001000 rw-p 00019000 16:07 972489     /lib/ld-2.4.90.so
bf9ed000-bfa03000 rw-p bf9ed000 00:00 0          [stack]
[anonymous@lor /]# ./a.out 14379 `printf %d 0xb7fde000` 4096
test_read: successful (Success)
test_mmap: shared failed (No such device)
test_mmap: private failed (No such device)


P.S. Код, конечно, не ахти, но в тестовых целях должен пойти.

anonymous
()
Ответ на: комментарий от anonymous

> Не могли бы вы назвать версию ядра, где вы видели подобное?
Да гугл-то на что? Вот, извольте-с:
http://lkml.org/lkml/2000/1/23/87

> Я же выше написал, что в Linux в настоящее время этот подход не
> используется.
А я написал, что использовался. И следовательно, реализуется не
так уж и сложно.

anonymous
()
Ответ на: комментарий от anonymous

> P.S. Код, конечно, не ахти, но в тестовых целях должен пойти.
А при чём тут ptrace()? Достаточно было просто на /proc/self/mem
mmap() сделать... хотя какой смысл, и так ясно, что на данный
момент это не работает. Этим много кто пользовался.

anonymous
()
Ответ на: комментарий от anonymous

>Да гугл-то на что? Вот, извольте-с:

>А я написал, что использовался. И следовательно, реализуется не так уж и сложно.

Думаю, что это была неработающая misfeature (к чему бы еще было удалять?). Впрочем, я скачаю ради прикола.

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

>А при чём тут ptrace()? Достаточно было просто на /proc/self/mem >mmap() сделать... хотя какой смысл, и так ясно, что на данный >момент это не работает. Этим много кто пользовался.

ptrace - чтобы, в частности, сработал read (а это нужно для наглядности). Чтобы read/mmap прошли в одинаковых условиях.

anonymous
()
Ответ на: комментарий от anonymous

системные вызовы? через LD_PRELOAD?

>	Системные вызовы через LD_PRELOAD отлично перехватываются.

Аж ни разу.  Можно статически слинковать бинарник. Можно сделать бинарник
SGID'ным.  Можно в .interp указать свой interpreter, который не обращает
внимания на LD_PRELOAD.

> По тому, что glibc их всех врапит.

На glibc свет клином не сошелся.

> Если бы ни это, то как бы работал, к примеру, aoss?

Что такое aoss? [google выдает явно не относящиеся к делу ссылки].

Dselect ★★★
()
Ответ на: комментарий от anonymous

>printf("test_read: %s (%s)\n", (pread64(fd, temp_area, size, start)==size)?"successful":"failed", strerror(errno));

Блин. 8-) Глюк с выводом strerror(errno), ведь оно может считаться в обратном порядке по отношению к read. В любом случае successful/failed выведется правильно.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.