Filtra os syscalls falhados do log de strace

1

Eu posso executar strace em um comando como sleep 1 e ver quais arquivos estão acessando assim:

strace -e trace=file -o strace.log sleep 1

No entanto, na minha máquina, muitas das chamadas têm um valor de retorno de -1 indicando que o arquivo não existe. Por exemplo:

$ grep '= -1 ENOENT' strace.log | head
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/locale/en_US.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

Eu não estou realmente interessado nos arquivos que não existem, Eu quero saber quais arquivos o processo realmente encontrou e leu. Além de grep -v '=-1 ENOENT' , Como posso filtrar com segurança as chamadas com falha?

    
por Nathaniel M. Beaver 06.04.2018 / 22:26

3 respostas

3

Além de pós-processar a strace de saída, não há nada disponível para ignorar chamadas de sistema com falha em strace . Não seria muito difícil adicionar, consulte a função syscall_exiting_trace em syscall.c .

Se você preferir seguir o ângulo de pós-processamento, Ole Tange já cuidou de que para você de uma forma mais abrangente do que você provavelmente chegará aqui: o tracefile A ferramenta executará strace e filtrará as informações que você procura de uma maneira legível. Consulte Listar os arquivos acessados por um programa para obter detalhes. Outra resposta para essa pergunta lista outras abordagens possíveis, incluindo LoggedFS que eu acho muito útil.

Outra opção é usar SystemTap ; por exemplo

#!/usr/bin/env stap

global stored_filename, stored_path

probe syscall.open {
  stored_filename = filename
}

probe syscall.open.return {
  if (execname() == "cat" && $return >= 0) {
    printf("opened %s\n", stored_filename)
  }
}

probe syscall.openat {
  stored_filename = filename
  stored_path = dfd_str
}

probe syscall.openat.return {
  if (execname() == "cat" && $return >= 0) {
    printf("opened %s in %s\n", stored_filename, stored_path)
  }
}

mostrará o nome de qualquer arquivo aberto com sucesso por qualquer processo cat .

    
por 31.05.2018 / 09:40
1

Possível solução:

strace -e trace=file sleep 1 2>&1 | grep -v "= -1 ENOENT" > strace.log
Por padrão,

strace imprime em stderr , portanto, redirecione-o para stdout .

    
por 06.04.2018 / 22:41
1

Um padrão ligeiramente mais confiável (ou seja, um risco ligeiramente menor de ignorar as linhas erradas por acidente) poderia ser

| grep -v "= -1 ENOENT [(]No such file or directory[)]$"

Ou seja. copie e cole o final da linha, "escapando" os colchetes (que poderiam ser tratados como caracteres especiais), e adicione o caractere especial $ ao final que "ancora" o padrão ao final da linha.

Não consigo encontrar uma opção melhor em man strace . Hackers de manipulação de texto rápidos e sujos são o Unix Way :-P.

É quase certamente possível fazer o que você quer com um script gdb personalizado. No entanto, isso é mais trabalho, e eu não tenho esse script preparado.

Outra questão faz referência a um script tracefile , que você executaria com a opção -e . Isso ainda é implementado analisando a saída de strace e, portanto, não parece ser completamente confiável, mas acho que é possível que você prefira. link

    
por 07.04.2018 / 11:00