Como devo determinar a utilização atual da rede?

9

Eu quero exibir a utilização atual da rede (uso de largura de banda) de uma interface de uma caixa Debian em um site. Não deveria ser muito elaborado ou preciso, apenas um número simples como "52 Mbit / s".

Os monitores típicos de largura de banda de rede, como por exemplo, iftopnão me permitem extrair esse valor.

Como posso recuperá-lo da melhor maneira?

Por exemplo, acho que posso analisar a /proc/net/devcada poucos minutos. Não tenho certeza se esta é realmente a melhor maneira de fazer isso.

Christoph Wurm
fonte

Respostas:

10

Eu acho que o ifstat irá ajudá-lo:

[root @ localhost ~] # ifstat -i eth0 -q 1 1
       eth0
 KB / s em KB / s de saída
 3390.26 69.69
migabi
fonte
7

A melhor maneira de fazer isso simplesmente é provavelmente analisar /proc/net/dev(lembre-se de que /procnão é portátil). Aqui está um bashscript que eu montei rapidamente que deve ser capaz de calculá-lo:

#!/bin/bash

_die() {
    printf '%s\n' "$@"
    exit 1
}

_interface=$1

[[ ${_interface} ]] || _die 'Usage: ifspeed [interface]'
grep -q "^ *${_interface}:" /proc/net/dev || _die "Interface ${_interface} not found in /proc/net/dev"

_interface_bytes_in_old=$(awk "/^ *${_interface}:/"' { if ($1 ~ /.*:[0-9][0-9]*/) { sub(/^.*:/, "") ; print $1 } else { print $2 } }' /proc/net/dev)
_interface_bytes_out_old=$(awk "/^ *${_interface}:/"' { if ($1 ~ /.*:[0-9][0-9]*/) { print $9 } else { print $10 } }' /proc/net/dev)

while sleep 1; do
    _interface_bytes_in_new=$(awk "/^ *${_interface}:/"' { if ($1 ~ /.*:[0-9][0-9]*/) { sub(/^.*:/, "") ; print $1 } else { print $2 } }' /proc/net/dev)
    _interface_bytes_out_new=$(awk "/^ *${_interface}:/"' { if ($1 ~ /.*:[0-9][0-9]*/) { print $9 } else { print $10 } }' /proc/net/dev)

    printf '%s: %s\n' 'Bytes in/sec'  "$(( _interface_bytes_in_new - _interface_bytes_in_old ))" \
                      'Bytes out/sec' "$(( _interface_bytes_out_new - _interface_bytes_out_old ))"

    # printf '%s: %s\n' 'Kilobytes in/sec'  "$(( ( _interface_bytes_in_new - _interface_bytes_in_old ) / 1024 ))" \
    #                   'Kilobytes out/sec' "$(( ( _interface_bytes_out_new - _interface_bytes_out_old ) / 1024 ))"

    # printf '%s: %s\n' 'Megabits in/sec'  "$(( ( _interface_bytes_in_new - _interface_bytes_in_old ) / 131072 ))" \
    #                   'Megabits out/sec' "$(( ( _interface_bytes_out_new - _interface_bytes_out_old ) / 131072 ))"

    _interface_bytes_in_old=${_interface_bytes_in_new}
    _interface_bytes_out_old=${_interface_bytes_out_new}
done

Lembre-se de que sleepnão considera a quantidade de tempo necessária para executar as operações no loop while, portanto, isso é (levemente) impreciso. Na minha mina de cobre de 600 mhz, o loop leva 0,011 segundos - uma imprecisão insignificante para a maioria dos propósitos. Lembre-se também ao usar as saídas de kilobyte / megabit (comentadas), o bash entende apenas a aritmética inteira.

Chris Down
fonte
Eu acho que essa deve ser a resposta escolhida. Todas as outras soluções se baseiam, nos bastidores, na análise /proc/net/dev, sem realmente entender o que e como essa mágica acontece.
Eran 27/04
Esta solução funcionou para mim em um roteador / busybox.
Cloneman 14/09/16
Use date +%s.%Npara obter o registro de data e hora do unix para cada iteração e divida a diferença de bytes pela diferença de registro de data e hora. Você evita que o problema das iterações de loop seja maior que 1s.
Arnavion 6/08/19
3

Existem monitores de tráfego de rede como o vnstat, que mantém registros mensais do seu tráfego, ou slurm, que obtém seus valores diretamente daqueles armazenados no kernel. Está disponível na maioria dos repositórios de distribuição.

Aqui está o que vejo quando executo slurm -i ra0:

insira a descrição da imagem aqui

invertido
fonte
1

Aqui está um script shell muito simples para calcular isso:

#!/bin/sh

dev=$1

grep -q "^$dev:" /proc/net/dev || exec echo "$dev: no such device"

read rx <"/sys/class/net/$dev/statistics/rx_bytes"
read tx <"/sys/class/net/$dev/statistics/tx_bytes"

while sleep 1; do
    read newrx <"/sys/class/net/$dev/statistics/rx_bytes"
    read newtx <"/sys/class/net/$dev/statistics/tx_bytes"

    # convert bytes to kbit/s: bytes * 8 / 1000 => bytes / 125
    echo "$dev  {rx: $(((newrx-rx) / 125)), tx: $(((newtx-tx) / 125))}"

    rx=$newrx
    tx=$newtx
done

basta iniciar o script passando o nome da interface, por exemplo. ./shtraf eth1

teknoraver
fonte
11
Você pode explicar isso um pouco? Exatamente qual deve ser o parâmetro? Qual é o significado de 125? Por favor, não responda nos comentários; edite sua resposta para torná-la mais clara e completa.
775 Scott Scott