首页 > 解决方案 > Bash 循环遍历多行 netstat 命令输出

问题描述

我正在运行此命令(将输出保存到文本文件:

netstat -ntp | grep tcp | grep EST | grep 34341

假设它具有以下输出(可以是单行或多行):

tcp      593      0 10.10.1.11:43856       10.10.2.14:3434      ESTABLISHED     146597/daemon-
tcp      417      0 10.10.1.11:43859       10.10.2.15:3434      ESTABLISHED     146567/daemon-
tcp      317      0 10.10.1.11:43121       10.10.2.16:3434      ESTABLISHED     146582/daemon-

到目前为止,这是我想出的(在阅读了您的评论之后):

#! /bin/bash

SLEEP=5
COUNTER=0

recvq()
{
    while read -r proto recvq x local remote state x
    do
        if [[ "$proto" == tcp && "$state" == ESTABLISHED && "$remote" =~ .*:3434 ]]
        then
            printf "%d\n" "$recvq"
        fi
    done < "$1"
}

while true; do

        (( COUNTER++ ))
        # measure recvq value
        declare -A first
        while read -r socket recvq
        do
            first[$socket]=$recvq
        done < <(recvq netstat1.txt)

        # sleep
        sleep "$SLEEP"

        # measure recvq value after sleep
        declare -A second
        while read -r socket recvq
        do
            second[$socket]=$recvq
        done < <(recvq netstat2.txt)

        [ ${#first[*]} != ${#second[*]} ] && { echo "Arrays are different size"; }

        for ii in ${!first[*]}; do
            [ "${first[$ii]}" == "${second[$ii]}" ] || { echo different element $ii; exit 1; }
        done
        echo "Arrays are identical"

done

现在我需要比较文件中每一行的 recvq 值(睡眠前)和 recvq 值(睡眠后)。如果任何初始 recvq 值与最终 recvq 值相同,则执行某些操作。

问题是我总是得到相同的数组,即使它们不是!

标签: bashshell

解决方案


我会这样解析:

#! /bin/bash

while read proto recvq x x port state x
do
  if [[ "$proto" == tcp && "$state" == ESTABLISHED && "$port" =~ .*:3434$ ]]
  then
    printf "%d\n" "$recvq"
  fi
done < <(netstat -ntp)

你不需要grepcatawk为此。

不要进行复制粘贴编程。如果你有代码,你想重用,把它放在一个函数中。

Bash 有关联数组,可以用来存储每个套接字接收到的数据。

#! /bin/bash

recvq()
{
  while read proto recvq x local remote state x
  do
    if [[ "$proto" == tcp && "$state" == ESTABLISHED && "$remote" =~ .*:3434$ ]]
    then
      printf "%s/%s %d\n" "$local" "$remote" "$recvq"
    fi
  done < "$1"
}

# First measure

declare -A first
while read socket recvq
do
  first[$socket]=$recvq
done < <(recvq netstat1.txt)

# Wait

sleep 10

# Second measure

declare -A second
while read socket recvq
do
  second[$socket]=$recvq
done < <(recvq netstat2.txt)

# Compare measures

for socket in "${!first[@]}"
do
  if [[ "${first[$socket]}" == "${second[$socket]}" ]]
  then
    printf "match for %s: %d\n" "$socket" "${first[$socket]}"
  fi
done

推荐阅读