AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / server / Perguntas / 11028
Accepted
deadprogrammer
deadprogrammer
Asked: 2009-05-22 14:14:23 +0800 CST2009-05-22 14:14:23 +0800 CST 2009-05-22 14:14:23 +0800 CST

Você tem algum script awk e grep útil para analisar logs do apache? [fechado]

  • 772
Fechado . Essa questão precisa ser mais focada . No momento não está aceitando respostas.

Quer melhorar esta questão? Atualize a pergunta para que ela se concentre apenas em um problema editando esta postagem .

Fechado há 7 anos .

Melhore esta pergunta

Posso usar analisadores de log, mas geralmente preciso analisar logs da web recentes para ver o que está acontecendo no momento.

Às vezes faço coisas como descobrir os 10 principais ips que solicitam um determinado arquivo

cat foo.log | grep request_to_file_foo | awk '{print $1}' |  sort -n | uniq -c | sort -rn | head

O que você tem na sua caixa de ferramentas?

logging apache-2.2 grep awk parsing
  • 12 12 respostas
  • 149579 Views

12 respostas

  • Voted
  1. Best Answer
    Mark
    2009-06-03T18:21:56+08:002009-06-03T18:21:56+08:00

    Você pode fazer praticamente qualquer coisa com arquivos de log do apache apenas com o awk. Os arquivos de log do Apache são basicamente separados por espaços em branco e você pode fingir que as aspas não existem e acessar qualquer informação de seu interesse pelo número da coluna. A única vez que isso é interrompido é se você tiver o formato de log combinado e estiver interessado em agentes do usuário, nesse ponto você terá que usar aspas ("") como separador e executar um comando awk separado. A seguir, você verá os IPs de cada usuário que solicita a página de índice classificada pelo número de acessos:

    awk -F'[ "]+' '$7 == "/" { ipcount[$1]++ }
        END { for (i in ipcount) {
            printf "%15s - %d\n", i, ipcount[i] } }' logfile.log
    

    $ 7 é o URL solicitado. Você pode adicionar quaisquer condições que desejar no início. Substitua o '$7 == "/" por qualquer informação que você queira.

    Se você substituir $1 in (ipcount[$1]++), poderá agrupar os resultados por outros critérios. Usar $7 mostraria quais páginas foram acessadas e com que frequência. É claro que você gostaria de alterar a condição no início. O seguinte mostraria quais páginas foram acessadas por um usuário de um IP específico:

    awk -F'[ "]+' '$1 == "1.2.3.4" { pagecount[$7]++ }
        END { for (i in pagecount) {
            printf "%15s - %d\n", i, pagecount[i] } }' logfile.log
    

    Você também pode canalizar a saída por meio de classificação para obter os resultados em ordem, como parte do comando shell ou também no próprio script awk:

    awk -F'[ "]+' '$7 == "/" { ipcount[$1]++ }
        END { for (i in ipcount) {
            printf "%15s - %d\n", i, ipcount[i] | sort } }' logfile.log
    

    O último seria útil se você decidisse expandir o script awk para imprimir outras informações. É tudo uma questão do que você quer descobrir. Estes devem servir como ponto de partida para o que você estiver interessado.

    • 61
  2. Dan Udey
    2009-06-06T13:46:45+08:002009-06-06T13:46:45+08:00

    Uma coisa que eu nunca vi ninguém fazer, por razões que não consigo imaginar, é mudar o formato do arquivo de log do Apache para uma versão mais facilmente analisável com as informações que realmente importam para você.

    Por exemplo, nunca usamos autenticação básica HTTP, portanto, não precisamos registrar esses campos. Estou interessado em quanto tempo cada solicitação leva para ser atendida , então vamos adicionar isso. Para um projeto, também queremos saber (em nosso balanceador de carga) se algum servidor está atendendo a solicitações mais lentas do que outros, então registramos o nome do servidor para o qual estamos fazendo proxy.

    Aqui está um trecho da configuração do apache de um servidor:

    # We don't want to log bots, they're our friends
    BrowserMatch Pingdom.com robot
    
    # Custom log format, for testing
    #
    #         date          proto   ipaddr  status  time    req     referer         user-agent
    LogFormat "%{%F %T}t    %p      %a      %>s     %D      %r      %{Referer}i     %{User-agent}i" standard
    CustomLog /var/log/apache2/access.log standard env=!robot
    

    O que você realmente não pode dizer disso é que entre cada campo há um caractere de tabulação literal (\t). Isso significa que se eu quiser fazer alguma análise em Python, talvez mostrar status não 200 por exemplo, posso fazer isso:

    for line in file("access.log"):
      line = line.split("\t")
      if line[3] != "200":
        print line
    

    Ou se eu quisesse fazer 'quem está fazendo hotlinking de imagens?' seria

    if line[6] in ("","-") and "/images" in line[5]:
    

    Para contagens de IP em um log de acesso, o exemplo anterior:

    grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" logfile | sort -n | uniq -c | sort -n
    

    fica algo assim:

    cut -f 3 log | uniq -c | sort -n
    

    Mais fácil de ler e entender e muito menos caro computacionalmente (sem regex), o que, em logs de 9 GB, faz uma enorme diferença em quanto tempo leva. Quando isso fica REALMENTE legal é se você quiser fazer a mesma coisa para os agentes do usuário. Se seus logs são delimitados por espaço, você precisa fazer alguma correspondência de expressão regular ou pesquisa de string manualmente. Com este formato, é simples:

    cut -f 8 log | uniq -c | sort -n
    

    Exatamente igual ao anterior. Na verdade, qualquer resumo que você queira fazer é basicamente o mesmo.

    Por que diabos eu gastaria a CPU do meu sistema em awk e grep quando cut fará exatamente o que eu quero ordens de magnitude mais rápido?

    • 25
  3. Vihang D
    2009-06-05T18:22:31+08:002009-06-05T18:22:31+08:00

    Esqueça o awk e o grep. Confira asql . Por que escrever scripts ilegíveis quando você pode usar sql como sintaxe para consultar o arquivo de log. Por exemplo.

    asql v0.6 - type 'help' for help.
    asql> load /home/skx/hg/engaging/logs/access.log
    Loading: /home/skx/hg/engaging/logs/access.log
    sasql> select COUNT(id) FROM logs
    46
    asql> alias hits SELECT COUNT(id) FROM logs
    ALIAS hits SELECT COUNT(id) FROM logs
    asql> alias ips SELECT DISTINCT(source) FROM logs;
    ALIAS ips SELECT DISTINCT(source) FROM logs;
    asql> hits
    46
    asql> alias
    ALIAS hits SELECT COUNT(id) FROM logs
    ALIAS ips SELECT DISTINCT(source) FROM logs;
    
    • 17
  4. anoopjohn
    2011-11-28T06:03:38+08:002011-11-28T06:03:38+08:00

    Aqui está um script para encontrar os principais URLs, principais referenciadores e principais agentes do usuário das entradas de log N recentes

    #!/bin/bash
    # Usage
    # ls-httpd type count
    # Eg: 
    # ls-httpd url 1000
    # will find top URLs in the last 1000 access log entries
    # ls-httpd ip 1000
    # will find top IPs in the last 1000 access log entries
    # ls-httpd agent 1000
    # will find top user agents in the last 1000 access log entries
    
    type=$1
    length=$2
    
    if [ "$3" == "" ]; then
      log_file="/var/log/httpd/example.com-access_log"
    else
      log_file="$3"
    fi
    
    if [ "$type" = "ip" ]; then
      tail -n $length $log_file | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | sort -n | uniq -c | sort -n
    elif [ "$type" = "agent" ]; then
      tail -n $length $log_file | awk -F\" '{print $6}'| sort -n | uniq -c | sort -n
    elif [ "$type" = "url" ]; then
      tail -n $length $log_file | awk -F\" '{print $2}'| sort -n | uniq -c | sort -n
    fi
    

    Fonte

    • 8
  5. f4nt
    2009-05-22T18:19:11+08:002009-05-22T18:19:11+08:00

    para contagens de IP em um log de acesso:

    cat log | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | sort -n | uniq -c | sort -n
    

    É um pouco feio, mas funciona. Eu também uso o seguinte com netstat (para ver conexões ativas):

    netstat -an | awk '{print $5}' | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | egrep -v "(`for i in \`ip addr | grep inet |grep eth0 | cut -d/ -f1 | awk '{print $2}'\`;do echo -n "$i|"| sed 's/\./\\\./g;';done`127\.|0\.0\.0)" | sort -n | uniq -c | sort -n
    

    Eles são alguns dos meus "one forros" favoritos :)

    • 5
  6. Kris
    2011-03-30T07:40:51+08:002011-03-30T07:40:51+08:00

    Aqui meu exemplo 'sed', ele lê o formato padrão dos logs do apache e o converte em algo mais conveniente para processamento automático. A linha inteira é definida como expressão regular, as variáveis ​​são salvas e gravadas na saída com '#' como separador.

    A notação simplificada da entrada é: %s %s %s [%s] "%s" %s %s "%s" "%s"

    Exemplo de linha de entrada: xx.xx.xx.xx - - [29/Mar/2011:12:33:02 +0200] "GET /index.html HTTP/1.0" 200 9443 "-" "Mozilla/4.0"

    Exemplo de linha de saída: xx.xx.xx.xx#-#-#29/Mar/2011:12:33:02 +0200#GET /index.html HTTP/1.0#200#9443#-#Mozilla/4.0

    cat access.log | \ 
      sed 's/^\(.*\) \(.*\) \(.*\) \[\(.*\)\] \"\(.*\)\" \(.*\) \(.*\) \"\(.*\)\" \"\(.*\)\"$/\1#\2#\3#\4#\5#\6#\7#\8#\9/g'
    

    Sinta o poder das expressões regulares :-)

    • 4
  7. ericslaw
    2009-06-06T13:34:03+08:002009-06-06T13:34:03+08:00

    Construir uma lista de perguntas comuns seria um ótimo índice para essas respostas a essa pergunta. Minhas dúvidas comuns são:

    • por que a taxa de acerto mudou?
    • por que o tempo de resposta geral está aumentando?'.

    Percebo essas mudanças monitorando as páginas de status do servidor (via mod_status) para taxa de acertos e tempo de resposta aproximado para solicitações ativas e concluídas recentemente (sabendo muito bem que sinto falta de uma enorme pilha de dados, mas as amostras são boas o suficiente).

    Eu uso a seguinte diretiva LogFormat (o %T é realmente útil)

    LogFormat "%h %l %u %t \"%r\" %>s %b 
        \"%{Referer}i\" \"%{User-Agent}i\" %T" custom
    

    Estou procurando causa-efeito e o que aconteceu primeiro... geralmente sobre subconjuntos específicos de padrões em meus logs, então preciso saber o seguinte para qualquer padrão/expressão regular:

    • hitcounts por intervalo (minuto ou hora) para um determinado padrão (endereço IP ou string ou parâmetros cgi, etc)
    • histogramas de tempo de resposta aproximado (usando o parâmetro %T)

    Eu geralmente uso perl, porque eventualmente fica complexo o suficiente para valer a pena.


    Um exemplo não-perl seria uma taxa de acerto rápida por minuto para códigos de status não 200:

    tail -9000 access_log | grep -v '" 200 ' | cut -d: -f2,3 | uniq -c
    

    Sim, estou trapaceando com esse grep, presumindo que um espaço de aspas-200-espaço corresponda apenas a códigos de status http .... poderia usar awk ou perl para isolar o campo, lembre-se de que pode ser impreciso.


    Um exemplo mais complexo em perl pode ser visualizar uma mudança na taxa de acerto de um padrão.

    Há muito o que mastigar no script abaixo, especialmente se você não estiver familiarizado com perl.

    • lê stdin para que você possa usar partes de seus logs, use tail (especialmente com tail -f), com ou sem greps e outros filtros ...
    • engana a extração de timestamp da época com hack de um regex e uso de Date::Manip
    • você pode modificá-lo apenas um pouco para extrair o tempo de resposta ou outros dados arbitrários

    código segue:

    #!/usr/bin/perl
    # script to show changes in hitrates for any regex pattern
    # results displayed with arbitrary intervals
    # and ascii indication of frequency
    # gaps are also displayed properly
    use Date::Manip;
    use POSIX qw(strftime);
    $pattern=shift || ".";
    $ival=shift || 60;
    $tick=shift || 10;
    $minb=undef;
    while (<>){
        next unless /$pattern/;
        $stamp="$1 $2" if m[(../.../....):(..:..:..)];
        $epoch = UnixDate(ParseDate($stamp),"%s");
        $bucket= int($epoch/$ival)*$ival;
        $minb=$bucket if $bucket<$minb || !defined($minb);
        $maxb=$bucket if $bucket>$maxb;
        $count{$bucket}++;
    }
    # loop thru the min/max range to expose any gaps
    for($t=$minb;$t<=$maxb;$t+=$ival){
        printf "%s %s %4d %s\n",
                $t,
                strftime("%m/%d/%Y %H:%M:%S",localtime($t)),
                $count{$t}+0,
                substr("x"x100,0,$count{$t}/$tick
        );
    }
    

    Se você deseja apenas processar métricas padrão, faça o checkout

    • 'mergelog' para reunir todos os seus logs (se você tiver vários apaches atrás de um balanceador de carga) e
    • webalizer (ou awstats ou outro analisador comum).
    • 3
  8. rkthkr
    2009-06-06T06:05:42+08:002009-06-06T06:05:42+08:00

    Quem está linkando suas imagens:

    awk -F\" '($2 ~ /\.(jpg|gif)/ && $4 !~ /^http:\/\/www\.mydomain\.com/){print $4}' access_log | sort | uniq -c | sort
    
    • 2
  9. Michael Steinfeld
    2011-11-19T19:19:57+08:002011-11-19T19:19:57+08:00

    Eu uso muito o awk dando tailing ou cat'ing o arquivo. Toda noite eu me entrego um relatório da web para cada servidor. Dependendo do seu arquivo de log e do seu LogFormat, você precisará editar alguns dos liners para trabalhar para você.. .

    Aqui está um exemplo simples:

    Se eu quiser seguir os logs no meu servidor para apenas códigos de status 404/500, eu faria isso:

    # $6 is the status code in my log file
    
    tail -f ${APACHE_LOG} |  awk  '$8 ~ /(404|500)/ {print $6}'
    

    <recorte>

    echo ""
    #echo  "Hits by source IP:"
    echo "======================================================================"
    
    awk '{print $2}' "$1" | grep -ivE "(127.0.0.1|192.168.100.)" | sort | uniq -c | sort -rn | head -25
    
    echo ""
    echo ""
    #echo "The 25 most popular pages:"
    echo "======================================================================"
    
    awk '{print $6}' "$1" | grep -ivE '(mod_status|favico|crossdomain|alive.txt)' | grep -ivE '(.gif|.jpg|.png)' | \
     sed 's/\/$//g' | sort | \
     uniq -c | sort -rn | head -25
    
    echo ""    
    echo ""
    echo "The 25 most popular pages (no js or css):"
    echo "======================================================================"
    
    awk '{print $6}' "$1" | grep -ivE '(mod_status|favico|crossdomain|alive.txt)' | grep -ivE '(.gif|.jpg|.png|.js|.css)' | \
     sed 's/\/$//g' | sort | \
       uniq -c | sort -rn | head -25
    
       echo ""
    
    
    #echo "The 25 most common referrer URLs:"
    echo "======================================================================"
    
    awk '{print $11}' "$1" | \
     grep -vE "(^"-"$|/www.$host|/$host)" | \
     sort | uniq -c | sort -rn | head -25
    
    echo ""
    
    #echo "Longest running requests"
    echo "======================================================================"
    
    awk  '{print $10,$6}' "$1" | grep -ivE '(.gif|.jpg|.png|.css|.js)'  | awk '{secs=0.000001*$1;req=$2;printf("%.2f minutes req time for %s\n", secs / 60,req )}' | sort -rn | head -50
    
    exit 0
    

    < /recorte>

    • 2
  10. Chris
    2012-05-29T14:28:01+08:002012-05-29T14:28:01+08:00

    A coisa que eu costumo fazer na maioria das vezes é ler seções de um log com base no tempo, então escrevi o seguinte script usando sed para extrair o período em que estou interessado, funciona em todos os arquivos de log que eu vim e também pode lidar com os logs arquivados.

    #!/bin/bash
    #Este script deve retornar um conjunto de linhas entre 2 valores, o objetivo principal é pesquisar um arquivo de log entre 2 vezes
    #Uso de script: arquivo logship.sh "start" "stop"
    
    #Se o arquivo contiver qualquer "/" no intervalo de datas, as 2 linhas a seguir adicionam o caractere de escape para que a pesquisa possa ser realizada por esses caracteres
    start=$(echo "$1" | sed 's/\//\\\//g')
    stop=$(echo "$2" | sed 's/\//\\\//g')
    
    zipped=$(echo "$3" | grep -c "gz$") #descobre se o arquivo está compactado ou não
    
    if [ "$zipado" == "1" ]; then #Se o arquivo estiver compactado, passe-o pelo zcat antes do sed
            zcat $3 | sed -n "/$iniciar/,/$parar/p";
    senão
            sed -n "/$iniciar/,/$parar/p" $3; #se não estiver zipado basta executar sed
    fi
    
    • 1

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Resolver o nome do host do endereço IP

    • 8 respostas
  • Marko Smith

    Como posso classificar a saída du -h por tamanho

    • 30 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    Qual é o utilitário de linha de comando no Windows para fazer uma pesquisa reversa de DNS?

    • 14 respostas
  • Marko Smith

    Como verificar se uma porta está bloqueada em uma máquina Windows?

    • 4 respostas
  • Marko Smith

    Qual porta devo abrir para permitir a área de trabalho remota?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    MikeN No Nginx, como posso reescrever todas as solicitações http para https mantendo o subdomínio? 2009-09-22 06:04:43 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    0x89 Qual é a diferença entre colchetes duplos e simples no bash? 2009-08-10 13:11:51 +0800 CST
  • Martin Hope
    kch Como altero a senha da minha chave privada? 2009-08-06 21:37:57 +0800 CST
  • Martin Hope
    Kyle Brandt Como funciona a sub-rede IPv4? 2009-08-05 06:05:31 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve