簡體   English   中英

Bash腳本超級慢

[英]Bash Script is super slow

我正在更新一個舊腳本來解析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
  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

但如果有多行,這仍然比純awk慢。 考慮一個像這樣簡單的awk腳本:

BEGIN {
    print "Parsing zTempMonth"
}   

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

NF == 4 {
    print $1 " " $3 " " $4
}   

你可以像這樣執行它:

awk -f thatAwkScript zTempMonth >> zTempMonth.tmp

獲得與當前腳本相同的附加方法。

編寫shell腳本時,直接調用函數而不是使用子shell調用函數幾乎總是更好。 我見過的通常慣例是回顯函數的返回值並使用子shell捕獲該輸出。 例如:

#!/bin/bash
function get_path() {
    echo "/path/to/something"
}
mypath="$(get_path)"

這樣可以正常工作,但是使用子shell有很大的速度開銷,而且有更快的替代方案。 相反,你可以只有一個約定,其中一個特定的變量總是函數的返回值(我使用retval)。 這還有一個額外的好處,也允許您從函數返回數組。

如果您不知道子shell是什么,為了本博客文章的目的,子shell是另一個bash shell,只要您使用$()或``並且用於執行您放入的代碼,就會生成它。

我做了一些簡單的測試,讓你觀察開銷。 對於兩個功能相同的腳本:

這個使用子shell:

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

這個使用變量:

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

這兩者之間的速度差異顯着且顯着。

$ 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

如您所見,使用variable ,執行需要0.367秒。 但是,子shell需要整整11.937秒!

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM