Оптимизация сценария оболочки с длительным циклом с условием продолжения

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

4
17.08.2013, 15:34
2 ответа

О, мой!

Я вижу, почему это берет навсегда для выполнения, Вы повторяете операции, не кэшируя информацию и в значительной степени избивая компьютер до смерти. Плохой Компьютер.:(

Awk не является легким весом, и Вы вызываете его многие, много раз по тем же данным. Я смог выполнить его однажды и установить все пять переменных.

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

Полагая, что ВСЯ обработка является grep's, awk's, sed's и TR, Вы могли получить впечатляющее повышение скорости путем записи этого сценария в Perl. Perl Разработан для обработки текста и отчетов. Это может сделать все те grep/awk/sed/tr внутренне, не выходя из оболочки к другой программе неоднократно.

Но вот некоторые улучшения:

if [ -s "$LOC/check.txt" ]; then

function setvars() {
    CONN_TSMP="$1"
    USER="$2"
    HOST="$3"
    DB="$4"
    IP="$5"
    return
}
    while read line; do
        echo " started processing ${line} at $(date) " >> "${SCRIPT_LOC}/running_status.txt"
        ID=$(echo "$line" | tr -d '"')
        # are you sure you don't want the FIRST match?  This will give ALL the matches,
        # which will prevent you from getting good values for the variables
        # to only get first entry that matches:
        # TST=$(grep --max-count=1 -w "$line" "$PERM_LOC/id_processing.txt")
        # (or -m 1, but long options document what you're doing better)
        TST=$(grep -w "$line" "$PERM_LOC/id_processing.txt")
        VARS=$(echo "${TST}" | awk -F '"' '{print "\""$2"\" \""$10"\" \""$18"\" \""$20"\" \""$22'})
        #                                        CONN_TSMP     USER      HOST      IP        DB
        # magic!  setvars receives the 5 values awk pulled out (ran it once!)
        # NO QUOTES on next line, already has them embedded from awk
        setvars $VARS

        if [ -z "$IP" ]; then
            IP="$HOST"
        fi

        CMD_TARGET="/data1/commands/user_commands"
        FILE="${ID}-${CONN_TSMP}-${USER}@${IP}.txt"

        if [ "$USER" == "root" ] && [ -z "$DB" ]; then
            TARGET="/data1/sessions/root_sec"
        else
            TARGET="/data1/sessions/user_sec"
        fi

        # does this need to be redirected to a file?
        ls "$TARGET/$FILE"
        if [ $? -ne 0 ]; then
            # awk can likely do the print and the removal of </> characters in
            # one pass (my awk-fu is weak this morning)
            echo "$TST" | awk -F 'STATUS="0"' '{print $2}'| sed "s/[</>]//g" >> "$TARGET/$FILE"
            echo -e "\n" >> "$TARGET/$FILE"
        fi

        # ALWAYS quote your values, embedded spaces will bite you!
        grep "$line" "$LOC/out.txt" > "$LOC/temp.txt"

        while read val; do
            TSMP=$(echo "$val" | awk -F '"' '{print $2}')
            QUERY=$(echo "$val" | awk -F 'SQLTEXT=' '{print $2}' | sed "s/[\"/]//g")
            echo " TIMESTAMP=$TSMP " >> "$TARGET/$FILE"
            echo " QUERY=$QUERY " >> "$TARGET/$FILE"
            TEXT=$(grep "$QUERY" "$PERM_LOC/commands.txt")
            if [ -n "$TEXT" ]; then
                NUM=$(expr $NUM + 1)
                # could also be:  NUM=$(($NUM+1)) (bash v4.0+)
                SUB_FILE="$ID-$command-$NUM-$TSMP-$USER@$IP.txt"
                echo -e "===============\n" > "$CMD_TARGET/$SUB_FILE"
                echo "FILE      =   \"$SUB_FILE\"" >> "$CMD_TARGET/$SUB_FILE"
                ### same way append 6 more lines to $SUB_FILE

                SUB=$(echo "$WARN_ME" | grep "$command")
                if [ "$command" == "$VC" ]; then
                    STATE=" very critical "
                elif [ -z "$SUB" ]; then
                    STATE=" CRITICAL "
                else
                    STATE=" WARNING "
                fi

                if [ "$USER" != "root" -a "$command" != "$VC" ]; then
                    # this should probably be $command instead of command?
                    # oh wait, probably a placeholder statement
                    mail command &
                elif [ "$USER" == "root" -a -z "$HOST" ]; then
                    mail command &
                elif [ "$USER" == "root" -a "$command" == "$VC" ]; then
                    mail command &
                else
                    echo -e "some message \n" >> $LOC/operations.txt
                fi
            fi
        done < "$LOC/temp.txt"
    done < "$LOC/check.txt"
fi

Хм, "сценарий оболочки только". Ну, имея это в виду, возможно, Вы могли pre-grep "$LOC/check.txt" и/или "$LOC/temp.txt" так, чтобы Вы могли использовать 'уже захваченный' вывод вместо того, чтобы держать в цикле.

Чем больше я смотрю на него, тем более убежден я, что awk мог, вероятно, сделать всю эту работу в единственной передаче через данные... И обработайте КАЖДУЮ запись, не только первую (как я указал в комментариях, Вам действительно нужен другой цикл между "строкой чтения", и "читают var" циклы.)

Это был бы длинный awk сценарий, но определенно выполнимый. И awk стоит знать, уделите минуту и играйте с ним, дело не в этом трудный, просто отличающийся. Grok Awk!

4
27.01.2020, 20:56
  • 1
    за воспроизведение.. я внес необходимые изменения, как Вы предположили, но тем не менее это занимает много времени приблизительно 5 и полчаса... Помогите мне проверить, спаривают цикл с awk решением..... Вы означаете получать check.txt в массив или что-то еще.... Помогите мне, у меня нет большого количества времени... я начал изучать awk и способный понять, но не способный разрешить вышеупомянутое с ним.... –  vidyadhar 18.08.2013, 21:04
  • 2
    Позвольте мне иметь по крайней мере 1 строку из каждого из следующих файлов, которые читаются в сценарии: $LOC/check.txt $LOC/out.txt $PERM_LOC/commands.txt $PERM_LOC/id_processing.txt Мне нужно это для определения надлежащих разделителей полей и положений полей. Можно отправить их в мой адрес электронной почты ($myname@$myname.com), если Вы хотели бы. (Вы поймете это!) –  lornix 19.08.2013, 10:50
  • 3
    здесь является 1-й строкой каждого файла... $LOC/check.txt ("123") ,$LOC/id_processing.txt (<МЕТКА ВРЕМЕНИ AUDIT_RECORD = "2013-08-16T15:54:48" ИМЯ = "Подключение" CONNECTION_ID = "6615427" СОСТОЯНИЕ = "0" ПОЛЬЗОВАТЕЛЬ = "ptwwuser" PRIV_USER = "ptwwuser" OS_LOGIN = "" PROXY_USER = "" ХОСТ = "" IP = "66 161 124 157" дБ = "CUST_PRESTIGEWW_DB"/>) ,$PERM_LOC/commands.txt (ОБНОВЛЕНИЕ) ,$LOC/out.txt (<МЕТКА ВРЕМЕНИ AUDIT_RECORD = "2013-08-16T17:19:23" ИМЯ = "Запрос" CONNECTION_ID = "6723567" СОСТОЯНИЕ = "0", SQLTEXT = "обновляют состояние набора MM_CAMPAIGN_SCHEDULE ='I' где id=292 и состояние ='U'"/>).... Любая справка очень полезна.. –  vidyadhar 19.08.2013, 14:47

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

Тем не менее, вот мое взятие при удалении всего sed и вызовов awk из Вашего сценария и упрощения его значительно, чтобы смочь отладить Ваши проблемы производительности правильно:

#!/usr/bin/env bash
# Should work using bash 3.2+ and the unrevealed part of your code

if [ ! -s "$LOC/check.txt" ]; then
    echo "Bummer!"
    exit 1
fi

function write_ts () {
    echo "[$(date)]: Started processing ${line}" >> ${SCRIPT_LOC}/running_status.txt
}

function set_and_init_file_targets () {
    if [ "$USER" == "root" ] && [ -z $DB ]; then
        TARGET=/data1/sessions/root_sec
        CMD_TARGET=/data1/commands/root_commands
    else
        TARGET=/data1/sessions/user_sec
        CMD_TARGET=/data1/commands/user_commands
    fi
    FILE="${CONNECTION_ID}-${TIMESTAMP}-${USER}@${IP}.txt"

    if [ ! -e "$TARGET/$FILE" ]; then
        echo "${_res##*STATUS=0}" > "$TARGET/$FILE"
    fi
}

function parse_line () {
    local line=$@

    while read val; do
        res2=${val//[<>\(\)]/}
        eval ${res2//AUDIT_RECORD/}
        SQLTEXT=${SQLTEXT/%?/}
        echo "TIMESTAMP=$TIMESTAMP" >> "$TARGET/$FILE"
        echo "QUERY=$SQLTEXT" >> "$TARGET/$FILE"

        /* grep the sql command by itself */
        TEXT=$(grep -i "${SQLTEXT%% *}" "$PERM_LOC/commands.txt")
        if [ -n "$TEXT" ]; then
            NUM=$((NUM + 1))
            SUB_FILE="$CONNECTION_ID-$command-$NUM-$TIMESTAMP-$USER@$IP.txt"
            echo -e "===============\n" > "$CMD_TARGET/$SUB_FILE"
            echo "FILE      =   \"$SUB_FILE\"" >> "$CMD_TARGET/$SUB_FILE"

            # [... the rest does not make sense at all ...]

        fi
    done < <(grep "$line" "$LOC/out.txt")
}

# Main code
while read line; do
    # grep line without quotes
    TST=$(grep -w "${line//\"/}" "$PERM_LOC/id_processing.txt")
    # remove everything besides key=val pairs
    res=${TST//[<>\(\)]/}
    # set the key=val pairs, except AUDIT_RECORD
    eval ${res//AUDIT_RECORD/}
    # set IP to HOST if empty
    : ${IP:="$HOST"}
    # remove nasty / at the end
    DB=${DB/%?/}
    set_and_init_file_targets
    parse_line "$line"
done < "$LOC/check.txt"

Отправив это, я на самом деле не убежден, что Ваша производительность выпускает основу от просто этих двух для циклов, вызывающих awk/sed/grep. Вы могли произвести первые десять строк Вашего ${SCRIPT_LOC}/running_status.txt когда Ваш сценарий работает в течение приблизительно одного часа?

Обратите внимание, что мои фрагменты сценария полностью не тестируются и не могли бы работать согласно Вашим ожиданиям. Однако я попытался следовать за семантикой Вашей первоначальной выборки сценария.

0
27.01.2020, 20:56

Теги

Похожие вопросы