Bash脚本超级慢

Rob*_*ert 2 bash performance

我正在更新一个旧脚本来解析ARP数据并从中获取有用的信息.我们添加了一个新的路由器,虽然我可以从路由器中提取ARP数据,但它是一种新的格式.我有一个文件"zTempMonth",它是来自两组路由器的所有arp数据,我需要编译成一个规范化的新数据格式.下面的代码行按逻辑方式执行我需要它们 - 但它非常慢 - 因为在以前脚本需要20-30分钟的情况下运行这些循环需要几天时间.有没有办法加快速度,或者找出减慢速度的方法?

先感谢您,

    echo "Parsing zTempMonth"
    while read LINE
    do
            wc=`echo $LINE | wc -w`
            if [[ $wc -eq "6" ]]; then
                    true
                    out=$(echo $LINE | awk '{ print $2 " " $4 " " $6}')
                    echo $out >> zTempMonth.tmp

            else
                    false
            fi

            if [[ $wc -eq "4" ]]; then
                    true
                    out=$(echo $LINE | awk '{ print $1 " " $3 " " $4}')
                    echo $out >> zTempMonth.tmp
            else
                    false
            fi


    done < zTempMonth
Run Code Online (Sandbox Code Playgroud)

koj*_*iro 6

  1. 虽然读循环很慢.
  2. 循环中的子shell很慢.
  3. >>(open(f, 'a'))循环中的调用很慢.

只需输掉#2和#3,你就可以加快速度并保持纯粹的狂欢:

#!/usr/bin/env bash

while read -a line; do
    case "${#line[@]}" in
        6) printf '%s %s %s\n' "${line[1]}" "${line[3]}" "${line[5]}";;
        4) printf '%s %s %s\n' "${line[0]}" "${line[2]}" "${line[3]}";;
    esac
done < zTempMonth >> zTempMonth.tmp
Run Code Online (Sandbox Code Playgroud)

但如果有多行,这仍然比纯awk慢.考虑一个像这样简单的awk脚本:

BEGIN {
    print "Parsing zTempMonth"
}   

NF == 6 {
    print $2 " " $4 " " $6
}   

NF == 4 {
    print $1 " " $3 " " $4
}   
Run Code Online (Sandbox Code Playgroud)

你可以像这样执行它:

awk -f thatAwkScript zTempMonth >> zTempMonth.tmp
Run Code Online (Sandbox Code Playgroud)

获得与当前脚本相同的附加方法.


Edu*_*omo 5

在编写 shell 脚本时,直接调用函数几乎总是比使用子 shell 调用函数更好。我见过的通常约定是回显函数的返回值并使用子外壳捕获该输出。例如:

#!/bin/bash
function get_path() {
    echo "/path/to/something"
}
mypath="$(get_path)"
Run Code Online (Sandbox Code Playgroud)

这工作正常,但使用子shell 有显着的速度开销,并且有一个更快的替代方案。相反,您可以有一个约定,其中特定变量始终是函数的返回值(我使用 retval)。这还有一个额外的好处,即还允许您从函数中返回数组。

如果您不知道子 shell 是什么,就本博文而言,子 shell 是另一个 bash shell,它在您使用$()或 `` 时生成,用于执行您放入其中的代码。

我做了一些简单的测试,让你观察开销。对于两个功能等效的脚本:

这个使用子shell:

#!/bin/bash
function a() {
    echo hello
}
for (( i = 0; i < 10000; i++ )); do
    echo "$(a)"
done
Run Code Online (Sandbox Code Playgroud)

这个使用了一个变量:

#!/bin/bash
function a() {
    retval="hello"
}
for (( i = 0; i < 10000; i++ )); do
    a
    echo "$retval"
done
Run Code Online (Sandbox Code Playgroud)

这两者之间的速度差异是显着且显着的。

$ for i in variable subshell; do
> echo -e "\n$i"; time ./$i > /dev/null
> done

variable

real 0m0.367s
user 0m0.346s
sys 0m0.015s

subshell

real 0m11.937s
user 0m3.121s
sys 0m0.359s
Run Code Online (Sandbox Code Playgroud)

如您所见,使用 时variable,执行时间为 0.367 秒。然而,subshel​​l 需要整整 11.937 秒!

资料来源:http : //rus.har.mn/blog/2010-07-05/subshel​​ls/