Итак, я пытаюсь выяснить, 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 и путь, но принимает пути источника и назначения.