Назад | Перейти на главную страницу

Процесс открыл индексный дескриптор, которого нет ни в одной файловой системе?

Итак, я пытаюсь выяснить, stderr процесса был перенаправлен на что-то необычное (это java-процесс, и мне нужен дамп потока, но он запускается через набор сценариев запуска).

Я нахожу свой процесс с pgrep, и используйте pfiles чтобы посмотреть, что там:

4366:   /foo/bar/platform/solaris2/jre_1.5.0/bin/java -Xmx2048m -Xms10
Current rlimit: 65536 file descriptors
 0: S_IFCHR mode:0666 dev:302,0 ino:6815752 uid:0 gid:3 rdev:13,2
    O_RDONLY|O_LARGEFILE
    /devices/pseudo/mm@0:null
 1: S_IFREG mode:0640 dev:85,56 ino:26471 uid:0 gid:0 size:10485812
    O_WRONLY|O_LARGEFILE
 2: S_IFREG mode:0640 dev:85,56 ino:26471 uid:0 gid:0 size:10485812
    O_WRONLY|O_LARGEFILE
 3: S_IFCHR mode:0666 dev:302,0 ino:6815772 uid:0 gid:3 rdev:13,12

Так что я вижу это stdout и stderr (файловые дескрипторы 1 и 2) указывают на одно и то же место; Я думаю, что они перенаправляются в один и тот же файл в сценариях запуска, так что это соответствует.

Но когда я ищу файл с номером inode 26471, я вижу следующее:

# find / -inum 26471
/usr/share/man/man3mlib/mlib_MatrixScale_S16_U8_Sat.3mlib
/proc/4366/fd/1
/proc/4366/fd/2
/proc/4366/fd/83

Первое попадание (я уверен) в файл в другой файловой системе. Три записи в /proc находятся файлы, открытые в моем процессе.

Ищу в /proc/4366, Я не вижу больше информации, чем получил от pfiles.

# ls -li 0 1 2 3
   6815752 c---------   1 root     sys       13,  2 Jan 20 14:10 0
     26471 --w-------   0 root     root     10485812 Jan 20 13:42 1
     26471 --w-------   0 root     root     10485812 Jan 20 13:42 2
   6815772 c---------   1 root     sys       13, 12 Jun  7  2009 3
# file 0 1 2 3
0:              character special (13/2)
1:              ascii text
2:              ascii text
3:              character special (13/12)

(Я могу отследить один из этих файловых десктопов и определить, какой это файл. Я спрашиваю, потому что я явно не понимаю взаимосвязь между fds и inode).

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

НАСКОЛЬКО МНЕ ИЗВЕСТНО, find ищет каталоги файловой системы. Если этот файл был удален, но все еще существует, потому что он открыт (обычная уловка в unix), он не будет найден find.

В Solaris не пробовал, но Вот примечание об использовании lsof для идентификации таких «удаленных, но открытых» файлов и восстановления через cat /proc/<procid>/fd/<fdid> > /tmp/xxxx

редактировать:

кажется, вы уже определили, что это так, но все еще задаетесь вопросом, как это возможно. вот краткое объяснение:

в файловой системе POSIX файлы обрабатываются ее inode, а каталоги - это не что иное, как отображение "путь => индексный дескриптор". У вас может быть более одного пути, «указывающего» на один и тот же индексный дескриптор (он называется жесткой ссылкой), а индексный дескриптор ведет счет количества ссылок, которые у него есть. В rm команда просто вызывает unlink() на этом пути, что уменьшает количество ссылок и «возможно» удаляет сам файл.

Но путь в дереве каталогов - не единственная возможная ссылка на индексный дескриптор, открытый fd в запущенном процессе также учитывается, и «удаленный» файл не будет удален, пока он не станет равным 0.

Как я уже упоминал выше, это распространенный трюк: если у вас есть временный файл, который вы не хотите сохранять после завершения работы вашего процесса, просто откройте его и немедленно «удалите». Открытый дескриптор будет работать надежно, и когда ваш процесс завершится (обычно, убит или выйдет из строя), система удалит дескриптор и чисто удалит временный файл.

Файл журнала не является вероятным кандидатом для такого «скрытого автоудаленного» файла; но это не сложно сделать случайно.

Поскольку ваш удаленный файл журнала все еще активен и собирает данные, кажется, что простое копирование содержимого не поможет. поэтому попробуйте создать новую жесткую ссылку на файл / proc // fd /, например, ln /proc/4366/fd/1 /tmp/xxxx. Обратите внимание, что нет -s флаг, так что ln должен создать новую жесткую ссылку с тем же индексом, что и исходный, а не символическую ссылку (которая представляет собой немного больше, чем указатель на существующий путь, а не то, что вы хотите).

редактировать:

В ln /proc/... /tmp/... команда не может работать, потому что / proc и / tmp находятся в разных файловых системах. К сожалению, я не знаю способа создать путь для существующего inode. Хотелось бы, чтобы link() syscall принимает номер inode и путь, но принимает пути источника и назначения.