Então, estou tentando descobrir se o stderr
processo foi redirecionado para algum lugar incomum (é um processo Java e quero um despejo de thread, mas ele é iniciado por meio de um conjunto de scripts de inicialização).
Eu encontro meu processo com pgrep
e uso pfiles
para ver o que está lá:
4366: /foo/bar/platform/solaris2/jre_1.5.0/bin/java -Xmx2048m -Xms10 Rlimit atual: 65536 descritores de arquivo 0: Modo S_IFCHR:0666 dev:302,0 ino:6815752 uid:0 gid:3 rdev:13,2 O_RDONLY|O_LARGEFILE /dispositivos/pseudo/mm@0:null 1: Modo S_IFREG:0640 dev:85,56 ino:26471 uid:0 gid:0 tamanho:10485812 O_WRONLY|O_LARGEFILE 2: Modo S_IFREG:0640 dev:85,56 ino:26471 uid:0 gid:0 tamanho:10485812 O_WRONLY|O_LARGEFILE 3: Modo S_IFCHR:0666 dev:302,0 ino:6815772 uid:0 gid:3 rdev:13,12
Então posso ver que stdout
e stderr
(descritores de arquivo 1 e 2) estão apontando para o mesmo lugar; Acho que eles são redirecionados para o mesmo arquivo nos scripts de inicialização, então isso corresponde.
Mas quando procuro um arquivo com número de inode 26471, vejo o seguinte:
#encontrar/-inum 26471 /usr/share/man/man3mlib/mlib_MatrixScale_S16_U8_Sat.3mlib /proc/4366/fd/1 /proc/4366/fd/2 /proc/4366/fd/83
O primeiro hit é (tenho certeza) um arquivo em um sistema de arquivos diferente. As três entradas /proc
são fds que meu processo abriu.
Olhando para dentro /proc/4366
, não consigo ver mais informações do que as que recebo pfiles
.
# ls -li 0 1 2 3 6815752 c------------- 1 root sys 13, 2 20 de janeiro 14:10 0 26471 --w ------- 0 raiz raiz 10485812 20 de janeiro 13:42 1 26471 --w ------- 0 raiz raiz 10485812 20 de janeiro 13:42 2 6815772 c --------- 1 root sys 13, 12 7 de junho de 2009 3 # arquivo 0 1 2 3 0: caractere especial (13/2) 1: texto ascii 2: texto ascii 3: personagem especial (13/12)
(Posso seguir um desses fds e descobrir qual arquivo é dele. Estou perguntando porque claramente não entendo a relação entre o fds e os inodes com profundidade suficiente).
Então meu processo é escrever paraalgo(em algum dispositivo, com inode 26471) e os dados vão para um arquivo com um número de inode diferente. Alguém pode me dar uma ideia do que pode ser isso (ou até mesmo me informar se meu raciocínio até agora está totalmente quebrado)?
Responder1
AFAIK, find
pesquisa os diretórios do sistema de arquivos. Se esse arquivo foi excluído, mas ainda existe porque está aberto (um truque comum no Unix), ele não será encontrado pelo find
.
Eu não tentei no Solaris, masaquié uma observação sobre o uso lsof
para identificar esses arquivos 'excluídos, mas abertos' e a recuperação por meio de umcat /proc/<procid>/fd/<fdid> > /tmp/xxxx
Editar:
parece que você já identificou que esse é o caso, mas ainda está se perguntando como isso é possível. aqui está uma breve explicação:
nos sistemas de arquivos POSIX, os arquivos são manipulados por seu inode
, e os diretórios são pouco mais que um mapeamento "path => inode". Você pode ter mais de um caminho 'apontando' para o mesmo inode (é chamado de hardlink), e o inode mantém uma contagem de quantos links possui. O rm
comando simplesmente chama unlink()
esse caminho, o que reduz a contagem de links e 'possivelmente' exclui o próprio arquivo.
Mas um caminho na árvore de diretórios não é a única referência possível para um inode, uma abertura fd
em um processo em execução também conta, e um arquivo 'excluído' não será realmente removido até chegar a 0.
Como mencionei acima, é um truque comum: se você tiver um arquivo temporário que não deseja manter após a execução do processo, basta abri-lo e 'excluí-lo' imediatamente. O identificador aberto funcionará de maneira confiável e quando o processo terminar (normalmente, encerrado ou travando), o sistema removerá o identificador e excluirá o arquivo temporário de forma limpa.
Um arquivo de log não é um candidato provável para esse arquivo de 'exclusão automática oculta'; mas não é difícil de fazer acidentalmente.
Como seu arquivo de log excluído ainda está ativo e coletando dados, parece que simplesmente copiar o conteúdo não ajudaria muito. então tente criar um novo hardlink para o arquivo /proc//fd/, algo como ln /proc/4366/fd/1 /tmp/xxxx
. Observe que não há -s
sinalizador, portanto, ln
crie um novo hardlink com o mesmo inode do original, não um link simbólico (que é pouco mais que um ponteiro para um caminho existente, e não o que você deseja).
Editar:
O ln /proc/... /tmp/...
comando não funciona porque /proc e /tmp estão em sistemas de arquivos diferentes. Infelizmente, não conheço nenhuma maneira de criar um nome de caminho para um inode existente. Seria desejável que o link()
syscall usasse um número de inode e um caminho, mas leva caminhos de origem e destino.