LINUX.ORG.RU

Скрипт мониторинга скорости сети врёт

 ,


0

1
  • Скрипт берёт байты из /proc/net/dev, ждёт секунду.
  • Берёт новые байты из /proc/net/dev
  • Вычитает из новых старые.

Я ожидал увидеть скорость в секунду, но скрипт врёт. Там где curl показывает 5.7mb — скрипт аж 6.2mb.

Подозреваю, что (время вычислений) + (1 секунда) по времени забирают больше одной секунды и я получаю скорость за 1.1 секунды, например.

Скрипт можно разнести на две части — (только вычитание) + (обёртка со всем остальным).

В этом случае значения скорости будут писаться в /tmp, а обёртка будет их использовать — таким образом я получу не скорость за 1.1 секунды, а скорость за 1.03 секунду, которая будет обновляться раз в 1.07 секунды.

Как *совсем* избавиться от погрешности, связанной со временем на вычитание?

Скрипт:

#!/bin/bash
 
SLEEP=1

function wrapper_net {
echo $(printf "%04s" $1 | sed "s/ /0/g")
}                
                
interface=eth0
 
get_bytes()
{
    line=$(cat /proc/net/dev | grep $interface | awk '{print "received_bytes="$2, "transmitted_bytes="$10}')
    eval $line
}
 
get_velocity()
{
    vel=$[$1-$2]
    
    if [ $vel -ge 1024 ] && [ $vel -lt 1048576 ] ;
    then
      velKB=$[vel/1024];
      echo "$(wrapper_net $velKB)K";
    elif [ $vel -ge 1048576 ];
    then
      velMB=$(echo "scale=1; $vel/1048576" | bc)
      echo "$(wrapper_net $velMB)M";
    else
      echo "$(wrapper_net $vel) ";
    fi
}
 
# Gets initial values.
get_bytes
old_received_bytes=$received_bytes
old_transmitted_bytes=$transmitted_bytes
 
# Loop
while :; do

get_bytes
 
vel_recv=$(get_velocity $received_bytes $old_received_bytes)
vel_trans=$(get_velocity $transmitted_bytes $old_transmitted_bytes)
 
old_received_bytes=$received_bytes
old_transmitted_bytes=$transmitted_bytes

echo -en "$vel_recv\t  $vel_trans\r"

sleep $SLEEP; done


Последнее исправление: ksevelyar (всего исправлений: 6)

Ты думаешь что только curl дергает сеть? И все-таки посмотри время исполнения скрипта?

kombrig ★★★
()
Ответ на: комментарий от kitar

Не хочу ставить внешние утилиты. Взял на заметку, но буду использовать только если не найду другого решения.

ksevelyar
() автор топика
Ответ на: комментарий от kombrig

Ну и погрешность в пределах 10% Ну и для увеличения точности неплохо бы взять более точный алгоритм диференцирования

kombrig ★★★
()
Ответ на: комментарий от kombrig
Ты думаешь что только curl дергает сеть? И все-таки посмотри время исполнения скрипта?

Уверен что только он.

Время выполнения (убрал цикл):

time ./network_speed.sh
0007K 0142K
real 0m1.016s
user 0m0.000s
sys 0m0.003s

Да, не сходится, должно быть от 1.07, но никак не 1.016.

Попробую в тело скрипта что-нибудь вставить для измерения.

Например, возьми формулу для диверенцирования назад

Матан :( Почитаю, спасибо.

ksevelyar
() автор топика

Там где curl показывает 5.7mb — скрипт аж 6.2mb

curl показывает скорость передачи чистых данных, а счетчик на интерфейсе весь (грязный) трафик.

sdio ★★★★★
()
Ответ на: комментарий от sdio

Мм, наверно.

vnstat тоже показывает 49.53 Mbit/s

Спасибо.

ksevelyar
() автор топика

line=$(cat /proc/net/dev | grep $interface | awk '{print «received_bytes=»$2, «transmitted_bytes=»$10}')

Не проще ли сразу

eval $(awk -v IF=$interface '($1==IF":"){print «received_bytes=»$2, «transmitted_bytes=»$10}' /proc/net/dev)

AITap ★★★★★
()
Ответ на: комментарий от ksevelyar

Возможны проблемы на некоторых ядрах между именем интерфейса и счетчиком нет пробела (eth0:2295070259)

$ cat /proc/net/dev
    lo: 2596475   12133    0    0    0     0          0         0  2596475   12133    0    0    0     0       0          0
  eth0:2295070259 3051024    0    0    0     0          0         0 2736063981 3107806    0    0    0     0       0          0
sdio ★★★★★
()
Ответ на: комментарий от sdio

У автора оригинала для этого было «cut -d ':' -f 2», но я проверил у себя на сервере (Дебиан) и на десктопе (Арч) — пробел есть. Так что решил выкинуть.

Со старыми ядрами нигде не пересекаюсь.

ksevelyar
() автор топика
Ответ на: комментарий от ksevelyar

Я когда-то написал подобный скрипт, только дергал ifconfig для доступа к счетчикам

cat if_speed.sh

#!/bin/bash
#
# usage: if_speed.sh [eth0] [time wait] [count]

# first option may be an interface name
IF=$1

#eth0 is a default if interface not specified
IF=${IF:=eth0}

     AWK=/usr/bin/awk
IFCONFIG=/sbin/ifconfig

# in seconds, default is 5 sec
SLEEP=$2
SLEEP=${SLEEP:=5}

# num of repeats, default is 1 time
COUNT=$3
COUNT=${COUNT:=1}

while [ $COUNT -gt 0 ]; do
    first=( `$IFCONFIG $IF | $AWK '/RX bytes/ { split($2,a,":"); \
                              split($6,b,":");                   \
                              print a[2], b[2]}'` )

    sleep $SLEEP

    $IFCONFIG $IF | $AWK -v p=$SLEEP -v r=${first[0]} -v t=${first[1]} '/RX bytes/ \
                    { split($2,a,":"); split($6,b,":"); \
                    printf("In:%.1fk Out:%.1fk\n", (a[2]-r)/p/1024, (b[2]-t)/p/1024)}'
COUNT=$((COUNT-1))
done
#------------------------------------------------------

$ ./if_speed.sh eth0 3 5
In:2.5k Out:76.2k
In:1.8k Out:74.1k
In:1.7k Out:65.9k
In:2.0k Out:76.2k
In:2.5k Out:61.5k
sdio ★★★★★
()
Ответ на: комментарий от sdio

Практика показывает что отваливаются только модули прекомпиляции для php. И то, раза два за год.

Всё остальное работает, несмотря на суицидальность сборки и грязные эксперименты.

ksevelyar
() автор топика
Ответ на: комментарий от sdio

Так он может как угодно измениться.

Если бы там всё было подписано, например: receive:27644631027 transmit:28860377578, то вытаскивать значение было бы по метке.

Если надёжность была бы в приоритете можно было бы распарсить данные по шапке. А раз уж всё базируется на номере поля — не вижу смысла в дополнительных манипуляциях.

ksevelyar
() автор топика
Ответ на: комментарий от ksevelyar

Внезапно велосипед с /proc/net/dev не нужен:

cat /sys/class/net/eth0/statistics/rx_bytes
cat /sys/class/net/eth0/statistics/tx_bytes

ksevelyar
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.