Como posso imprimir leituras e gravações atuais no sistema de arquivos por demanda?

2

Estou interessado em obter estatísticas sobre leituras e gravações do sistema de arquivos, especificamente para uma montagem NFS.

Eu sei que existem muitas ferramentas, como iostat , nfsstat e inotifywait , mas há problemas que tenho com cada programa.

Não consigo usar nada que exija que eu passeie pelo sistema de arquivos ou mencione explicitamente nomes de arquivos devido à complexidade da hierarquia.

Existe um programa que pode fazer o seguinte sob demanda?

  1. mostrar leituras / gravações
  2. mostra o caminho da leitura / gravação
  3. mostrar quantidade de bytes

Por demanda, quero dizer, em tempo de execução. O ponto (3) não é obrigatório.

Por exemplo, gostaria de poder fazer algo como o seguinte:

$ magicIOprogram
read, 512, /path/to/file1
read, 256, /path/to/file2
write, 15, /path/to/file3
write, 10562, /path/to/file4

Se houver maneiras de obter essas informações usando as ferramentas mencionadas anteriormente que eu desconheço, também seria uma solução adequada.

    
por Nathan McCoy 13.07.2015 / 12:05

2 respostas

1
auditd do Linux pode obter as informações para os pontos 1 e 2.

Supondo que você esteja executando o RHEL / CentOS 6 e tenha um compartilhamento nfs montado como /mnt/nfs/foo :

$ tree /mnt/nfs/foo
/mnt/nfs/foo
|-- a
|   '-- foo
|-- b
    '-- bar

Você precisará definir as seguintes regras em /etc/audit/audit.rules :

# Delete existing rules
-D
# Set buffer size
-b 320
# Log read and write operations
-w /mnt/nfs/foo -p r -k read -k nfs
-w /mnt/nfs/foo -p w -k write -k nfs

Em seguida, recarregue o serviço auditd com /etc/init.d/auditd reload .

Uma vez feito isso, você pode usar ausearch e aureport para ler os registros de eventos gerados por auditd :

$ cat /mnt/nfs/foo/a/foo
$ echo 'test' > /mnt/nfs/foo/b/bar
$ ausearch -k nfs | aureport -f
File Report
===============================================
# date time file syscall success exe auid event
===============================================
1. 07/15/2015 11:39:04 /mnt/nfs/foo/a/foo 2 yes /bin/cat 500 59
2. 07/15/2015 11:39:05 /mnt/nfs/foo/b/bar 2 yes /bin/bash 500 60

Uma ressalva de que ele só poderá coletar as informações do lado do cliente. Se o seu cliente não é confiável, você não pode usar este método para determinar com segurança o que eles estão acessando através do nfs.

    
por 15.07.2015 / 13:17
2

Você pode querer tentar systemtap .

Aqui está um exemplo ligeiramente modificado mostrando as aberturas, leituras e gravações a cada 100 ms:

#! /usr/bin/env stap

global fileread, filewrite

probe syscall.open.return {
    if ($return != -1) {
        printf("open, %s, %d/%d\n", user_string($filename), pid(), $return)
    }
}

probe syscall.read.return {
    p = pid()
    fd = $fd
    bytes = $return
    if (bytes > 0)
        fileread[p, fd] += bytes
}

probe syscall.write.return {
    p = pid()
    fd = $fd
    bytes = $return
    if (bytes > 0)
        filewrite[p, fd] += bytes
}

probe timer.ms(100) {
    foreach (v = [p,fd] in fileread) {
        printf("read, %d, %d/%d\n", v, p, fd)
    }                                                                                                                                                                                          
    delete fileread                                                                                                                                                                            
    foreach (v = [p,fd] in filewrite) {                                                                                                                                                        
        printf("write, %d, %d/%d\n", v, p, fd)                                                                                                                                                 
    }                                                                                                                                                                                          
    delete filewrite                                                                                                                                                                           
}

O formato das linhas de saída é:

  • aberto, (nome do caminho), (pid) / (fd)

  • ler, (bytes), (pid) / (fd)

  • escreva, (bytes), (pid) / (fd)

por 18.07.2015 / 01:13