Поэтому я пытаюсь выяснить, не stderr
был ли процесс перенаправлен куда-то необычным образом (это процесс Java, и мне нужен дамп потока, но он запускается через набор стартовых скриптов).
Я нахожу свой процесс с помощью pgrep
и использую, pfiles
чтобы посмотреть, что там:
4366: /foo/bar/platform/solaris2/jre_1.5.0/bin/java -Xmx2048m -Xms10 Текущий лимит: 65536 файловых дескрипторов 0: S_IFCHR режим: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 режим:0640 dev:85,56 ino:26471 uid:0 gid:0 размер:10485812 O_WRONLY|O_LARGEFILE 2: S_IFREG режим:0640 dev:85,56 ino:26471 uid:0 gid:0 размер:10485812 O_WRONLY|O_LARGEFILE 3: S_IFCHR режим:0666 dev:302,0 ino:6815772 uid:0 gid:3 rdev:13,12
Итак, я вижу, что stdout
и stderr
(файловые дескрипторы 1 и 2) указывают на одно и то же место; я думаю, что они перенаправлены на один и тот же файл в скриптах запуска, так что это совпадает.
Но когда я ищу файл с номером инода 26471, я вижу это:
# найти / -inum 26471 /usr/share/man/man3mlib/mlib_MatrixScale_S16_U8_Sat.3mlib /proc/4366/fd/1 /проц/4366/фд/2 /проц/4366/фд/83
Первое попадание (я уверен) — файл на другой файловой системе. Три записи — /proc
это fds, которые открыл мой процесс.
Заглянув туда /proc/4366
, я не вижу больше информации, чем получаю от pfiles
.
# ls -li 0 1 2 3 6815752 c--------- 1 root sys 13, 2 янв. 20 14:10 0 26471 --w------- 0 root root 10485812 20 января 13:42 1 26471 --w------- 0 root root 10485812 20 января 13:42 2 6815772 c--------- 1 root sys 13, 12 7 июня 2009 3 # файл 0 1 2 3 0: специальный символ (13/2) 1: текст ascii 2: текст ascii 3: особый персонаж (13/12)
(Я могу отследить один из этих fds и по нему определить, какой это файл. Я спрашиваю, потому что явно не понимаю достаточно глубоко взаимосвязь между fds и inode).
Итак, мой процесс заключается в том, чтобы писатьчто-нибудь(на каком-то устройстве с инодом 26471) и данные затем попадают в файл с другим номером инода. Может ли кто-нибудь дать мне представление о том, что это может быть (или даже дать мне знать, если мои рассуждения до сих пор полностью сломаны)?
решение1
AFAIK, find
ищет в каталогах файловой системы. Если этот файл был удален, но все еще существует, потому что он открыт (обычный трюк в unix), он не будет найден find
.
Я не пробовал в Solaris, ноздесьесть заметка об использовании lsof
для идентификации таких «удаленных, но открытых» файлов и восстановлении с помощьюcat /proc/<procid>/fd/<fdid> > /tmp/xxxx
Редактировать:
кажется, вы уже определили, что это так, но все еще задаетесь вопросом, как это возможно. Вот краткое объяснение:
В файловых системах POSIX файлы обрабатываются его inode
, а каталоги представляют собой не более чем сопоставление "путь => inode". У вас может быть более одного пути, "указывающего" на один и тот же inode (это называется жесткой ссылкой), и inode ведет подсчет количества ссылок, которые у него есть. Команда rm
просто вызывает unlink()
этот путь, что уменьшает количество ссылок и "возможно" удаляет сам файл.
Но путь в дереве каталогов — это не единственная возможная ссылка на inode, открытие fd
в запущенном процессе также учитывается, а «удаленный» файл не будет по-настоящему удален, пока его значение не достигнет 0.
Как я уже упоминал выше, это распространенный трюк: если у вас есть временный файл, который вы не хотите сохранять после завершения процесса, просто откройте его и немедленно «удалите». Открытый дескриптор будет работать надежно, и когда ваш процесс завершится (нормально, убит или аварийно), система удалит дескриптор и аккуратно удалит временный файл.
Файл журнала вряд ли является подходящим кандидатом на роль такого «скрытого автоудаляемого» файла, но это несложно сделать случайно.
Поскольку ваш удаленный файл журнала все еще активен и собирает данные, похоже, простое копирование содержимого не поможет. поэтому попробуйте создать новую жесткую ссылку на файл /proc//fd/, что-то вроде ln /proc/4366/fd/1 /tmp/xxxx
. Обратите внимание, что флага нет -s
, поэтому ln
следует создать новую жесткую ссылку с тем же inode, что и у оригинала, а не символическую ссылку (которая представляет собой не более чем указатель на существующий путь, а не то, что вам нужно).
Редактировать:
Команда ln /proc/... /tmp/...
не может работать, поскольку /proc и /tmp находятся в разных файловых системах. К сожалению, я не знаю способа создать имя пути для существующего inode. Можно было бы захотеть, чтобы link()
системный вызов принимал номер inode и путь, но он принимает исходный и целевой пути.