【问题标题】:Bash loop through multiple lines of netstat command outputBash 循环遍历多行 netstat 命令输出
【发布时间】:2020-05-18 16:55:53
【问题描述】:

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

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-

这是我到目前为止的想法(在阅读了您的 cmets 之后):

#! /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 值相同,则执行某些操作。

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

【问题讨论】:

  • 不要写论文。缩小你的问题。减少到实际问题。 minimal reproducible example
  • 我已经创建了单行输出所需的脚本,但我无法弄清楚多行输出这是否意味着循环输出还不够?它是上下文敏感的吗?您的实际问题在哪里(预期与观察到的行为)?
  • 对于单行输出,它工作正常。我想让它适用于任何输出,我的意思是单行、2 行或任意行数的输出
  • @BogdanStoica :首先,我将删除grep 3434,因为稍后您将再次检查此端口。然后我会扔掉两个标题行。这将为您提供表格形式的数据,以空格分隔。然后,您可以使用 awk 选择正确的行并收集 recv-Q 值并将它们写入标准输出 - 如果需要,您可以将其捕获到 bash 数组中。
  • 感谢您的信息,这就是我想做的事情,但没有成功;(

标签: bash shell


【解决方案1】:

我会这样解析:

#! /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

【讨论】:

  • 您忘记向循环提供输入。另外,我认为 OP 希望不打印 recvq 值,而是将它们累积到一个 bash 数组中,也许以后再处理它们。
  • 没错,我想保存 recvq 值并与其他值进行比较
  • 谢谢 cevig。你提到的方式更容易和更短的代码......
  • 它似乎在工作,但有些东西不好。条目没有以正确的顺序显示,而且输出有点奇怪:13:31:06 ▶ ./f.sh match for 101: 0 match for 103: 0 match for 102: 0 match for 104: 0。在文件中我有 101,102,103,104 除了第二个文件中的最后一行是 105。所以它应该只显示我猜的匹配条目
  • 所以如果我打印时有 100 200 300 400 它会显示 100 300 200 400 而不是订单.. 我真的不明白
【解决方案2】:

我终于想通了。正如@ceving 所建议的那样,它可能与关联数组一起工作得很好,并且也提供了一个答案,但它没有按预期工作。

不过,我不会将自己的答案标记为正确的答案。我刚刚发布它以防任何人发现它有用。

#/bin/bash

n1="$(cat netstat1.txt | awk '{split($5,a,":"); print a[1]"="$2}')"

sleep 5

n2="$(cat netstat2.txt | awk '{split($5,a,":"); print a[1]"="$2}')"

# check
for i in $n1; do
    ip1=`echo $i | awk '{split($i,a,"="); print a[1]}'`
    val1=`echo $i | awk '{split($i,a,"="); print a[2]}'`
    #echo $ip1 $val1

    for j in $n2; do

        ip2=`echo $j | awk '{split($j,a,"="); print a[1]}'`
        val2=`echo $j | awk '{split($j,a,"="); print a[2]}'`
        #echo $ip2 $val2

        if [ $ip1 == $ip2 ]; then
            if [ $val1 == $val2 ]; then
                echo "values: $val1 vs $val2 equal for remote ip: $ip1 => NOK! Do whatever!"
            else
                echo "values: $val1 vs $val2 dfferent for remote ip: $ip1 => OK"
            fi
        fi
    done
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 2021-01-02
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 2016-12-15
    • 2012-10-28
    相关资源
    最近更新 更多