Добрового времени суток друзья. Я столкнулся с маленькои проблемой, которая никак не решается. Может вы сможете помочь.
У меня написан следуюший скрипт:

#!/bin/bash
log="/etc/openvpn/openvpn.log"
msg="Peer Connection Initiated with"
tmp_file="/etc/openvpn/log.tmp"
mailbox="myemail@whatever.com"
while [ : ]
do
                tac $log | while read line; do
                        if [[ $line =~ "^checkAndSend" ]] ;then
                                break;
                        else
                                echo $line >> $tmp_file;
                        fi
                done
                echo "checkAndSend" >> $log
#----------------------------------------------------------------
                data=`egrep -wi "$msg" $tmp_file`
                if [ -n "$data" ] ; then
                        echo "$data"|mail -s "`echo $data|head -n1|awk {'print($7" connected by VPN from "$6)'}| sed 's/openvpn-//g'| cut -d: -f1`" $mailbox
                fi
                :> $tmp_file
sleep 30
done

Этот скрипт присылает мэил, когда кто-то из работников подсоединяется к OpenVPN серверу при помощи клиента.
На CentOS release 5.5 (Final) этот скрипт работал без проблем, но при переходе на CentOS release 6.2 (Final) он подвисает и отсылает одно и тоже уведомление снова и снова. Может кто-нибудь видит в чем проблема или предложит лучший способ?
Заранее спасибо.

2

Если ты предоставишь примеры файлов, будет проще проверить.
И что делает оператор =~?

3

Vascom пишет:

И что делает оператор =~?

http://tldp.org/LDP/abs/html/bashver3.h … EXMATCHREF

Был, был и весь вышел...

4

Lupo Alberto пишет:
Vascom пишет:

И что делает оператор =~?

http://tldp.org/LDP/abs/html/bashver3.h … EXMATCHREF

Замечательно ab
Там же написано

# NOTE: As of version 3.2 of Bash, expression to match no longer quoted.

Это оно? Надо кавычки убрать?

5

Vascom пишет:

Это оно? Надо кавычки убрать?

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

Был, был и весь вышел...

6

Cпасибо за ответ друзья. Очень помогли.

7

Так в чём была проблема?

8

Vascom пишет:

Так в чём была проблема?

кавычки =)

9

С вашего разрешения, друзья, посветим эту тему скриптам =)
Я пытаюсь написать скрипт, который будет отсылать email если количество соединений превысит установленный предел.
Т.е. один пользователь пытается закидать сервак запросами. Вот что у меня получилось:

#!/bin/bash
while [ : ]
do
        netstat -ntu | awk '{print $5}' | awk '!/[A-Z]/' | cut -d: -f1 | sort | uniq -c | sort -n 
                if [[ $line > 30 ]] ;then
                        break;
                else
                        echo $line >> result2;
                fi
done
#-------------------------------------------------------------------------------------------
                        cat result2 | mail -s "Some gay hit API limit" myemail@whatever.com
:> result2
done

Строго не судите, только учусь
Я использую команду netstat, для того чтобы получить список IP адресов и сколько соединений установленно с каждым IP:

 netstat -ntu | awk '{print $5}' | awk '!/[A-Z]/' | cut -d: -f1 | sort | uniq -c | sort -n 

Получается вот что:

      1 149.152.191.3
      1 164.50.244.203
      2 173.164.45.221
      4 173.64.11.26

Затем(вот тут вопрос):

if [[ $line > 1 ]] ;then
                        break;
                else
                        echo $line >> result2;
                fi
done

Как лучше проверить есть ли в первом столбике число, например, больше 30. И если такая линия имеется, то переместить её в отдельный фаил вместе с IP адресом. Естественно я понимаю, что if [[ $line > 1 ]] ;then .... совершенно не правильно, просто пытался кое-что изобразить, но вообше не получилось, пардоньте.

Ну и финальная стадия, отправить содержимое фаила на определеный email и очистить фаил.
Подскажите пожалуиста как дописать скрипт, либо может эту задачу можно решить иным способом.
Спасибо.

10

На коленке можно так сделать, правда пришлось избавляться от пробелов, но их точно так же можно и вернуть, если надо:

#!/bin/bash

#Удаляем старый файл
rm flame_file.log
#Задаём порог срабатывания
thr=1

full_line=`netstat -ntu | awk '{print $5}' | awk '!/[A-Z]/' | cut -d: -f1 | sort | uniq -c | sort -n`

#Заменяем пробелы на ",", чтобы проще было обрабатывать в цикле for
full_line_s=`echo "$full_line" | sed 's/ /,/g'`

for line in $full_line_s
do
    #Вычленяем нужные числа
    check=`echo "$line" | cut -d "," -f7`

    #Проверяем превышение порога
    if (( $check > $thr ))
    then
        echo "$line" >> flame_file.log
    fi
done

Как отправить письмо ты уже знаешь, файл очищается rm (в моём примере), либо через echo "" > flame_file.log.

Этот вариант написан за пару минут, можно доработать и вылизать его.

11

NewbieUNIX пишет:

Как лучше проверить есть ли в первом столбике число, например, больше 30. И если такая линия имеется, то переместить её в отдельный фаил вместе с IP адресом.

Команда

netstat -ntu | awk '$5 ~ /[0-9]/ {print $5}' | cut -d: -f1 | sort | uniq -c | sort -n | awk '$1 > 30 {print $2}'

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

Был, был и весь вышел...

12

Кстати, iptables может логировать (и при желании блокировать) превышение запросов за определённый промежуток времени.

Был, был и весь вышел...

13

Vascom пишет:

На коленке можно так сделать, правда пришлось избавляться от пробелов, но их точно так же можно и вернуть, если надо:

#!/bin/bash

#Удаляем старый файл
rm flame_file.log
#Задаём порог срабатывания
thr=1

full_line=`netstat -ntu | awk '{print $5}' | awk '!/[A-Z]/' | cut -d: -f1 | sort | uniq -c | sort -n`

#Заменяем пробелы на ",", чтобы проще было обрабатывать в цикле for
full_line_s=`echo "$full_line" | sed 's/ /,/g'`

for line in $full_line_s
do
    #Вычленяем нужные числа
    check=`echo "$line" | cut -d "," -f7`

    #Проверяем превышение порога
    if (( $check > $thr ))
    then
        echo "$line" >> flame_file.log
    fi
done

Как отправить письмо ты уже знаешь, файл очищается rm (в моём примере), либо через echo "" > flame_file.log.

Этот вариант написан за пару минут, можно доработать и вылизать его.

Скрипт интересный, спасибо большое.
На линии 19 он сравнивает IP с лимитом количества подключений, хотя должен сравнивать лимит подлючений и кол-во подключений с одного IP.

 line 19: ((: 209.40.97.5 > 1 : syntax error: invalid arithmetic operator (error token is ".40.97.5 > 1 ")

Или я чего-то не понимаю?
Спасибо

14

Да, это я коряво с пробелами разобрался ab
Конечно надо было через awk, как-то забываю про него.

Ну разберись в скрипте, если хочешь, там все команды элементарные.
Надо отредактировать строку
check=`echo "$line" | cut -d "," -f7`
подобрать нужное поле, то есть не -f7, а -f6 или -f5 или ещё меньше.

15

Vascom пишет:

Да, это я коряво с пробелами разобрался ab
Конечно надо было через awk, как-то забываю про него.

Ну разберись в скрипте, если хочешь, там все команды элементарные.
Надо отредактировать строку
check=`echo "$line" | cut -d "," -f7`
подобрать нужное поле, то есть не -f7, а -f6 или -f5 или ещё меньше.

Да конечно ab  Ещё раз огромное спасибо  ay
Просто хотел убедиться, что понимаю о чём речь.
Позже виложу конечный вариант.

16

Вот что получилось. Vascom и Lupo Alberto огромное спасибо.

#!/bin/bash

thr=30

full_line=`netstat -ntu | awk '{print $5}' | awk '!/[A-Za-z]/' | cut -d: -f1 | sort | uniq -c | sort -n`

full_line_s=`echo "$full_line" |  awk '{print $1}'`

for line in $full_line_s
do

    check=`echo "$line" | awk '{print $1}'`
###############################################################
host=`hostname`
mailbox="myemail@whatever.com"
data=`netstat -ntu | awk '$5 ~ /[0-9]/ {print $5}' | cut -d: -f1 | sort | uniq -c | sort -n | awk '$1 > 30 {print $2}'`
###############################################################
    #check limits
    if (( $check > $thr ))
    then
        echo "Some text here: $data"|mail -s "Some text here $host" $mailbox
    fi
done

17

Помогите пожалуйста оптимизировать:

date | awk '{print $3,$2,$6,$4}' | sed 's/ /\//' | sed 's/ /\//' | sed 's/ /\:/' | cut -d: -f1,2,3

Пытаюсь вывод команды "date" трансформировать, вместо

Tue Dec 11 13:35:32 EST 2012

получить следующее:

11/Dec/2012:13:35

Мой вариант работает, но я понимаю что можно сделать проще, только не знаю как. Буду очень благодарен за подсказку.
Спасибо.

18

date +%d/%b/%Y:%H:%M
Был, был и весь вышел...

19

Lupo Alberto пишет:
date +%d/%b/%Y:%H:%M

Спасибо.

20 (14.12.2012 23:17:07 отредактировано NewbieUNIX)

Добрового времени суток. Помогите дописать скрипт пожалуйста.

1шаг: Проверяю еррор логи на наличие ошибки, на выходе из команды получаю название домена

grep "$min_1" $log_er | grep limiting | awk '{print $16}' | sed 's/,/ /g' 

2шаг: Потом сравниваю с именами домена. Если какои-то домен подходит, то проверяю другие логи, чтобы узнать количество соединений

     if [[ $line =~ ^domain1.com ]] ;then
                                full_line=`grep "$min_2" $log_2 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        fi
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                        elif [[ $line =~ ^domain2.com ]] ;then
                                full_line=`grep "$min_2" $log_2 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                         elif [[ $line =~ ^domain3.com ]] ;then
                                full_line=`grep "$min_2" $log_3 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                        elif [[ $line =~ ^domain4.com ]] ;then
                                full_line=`grep "$min_2" $log_4 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                else
                        break;
        fi
                done

3шаг: Если лимит превышен, то отправляю емаил

do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi

Весь скрипт:

#!/bin/bash

#Setup limit
thr=900
#-----------------------------------------------------------------------------------------------------
#Time
min_1=`date '+%G/%m/%d %H:%M'`
min_2=`date +%d/%b/%Y:%H:%M`
#-----------------------------------------------------------------------------------------------------
#nginx error log file
log_er="/var/log/nginx/error.log"
#-----------------------------------------------------------------------------------------------------
#log files
log_1="/etc/nginx/logs/domain1.com.ssl.log"
log_2="/etc/nginx/logs/domain2.com.ssl.log"
log_3="/etc/nginx/logs/domain3.com.ssl.log"
log_4="/etc/nginx/logs/domain4.com.ssl.log"
#-----------------------------------------------------------------------------------------------------
#Information for email
#From hostname
host=`hostname`
#-----------------------------------------------------------------------------------------------------
#To
mailbox="myemail@whatever.com"
#-----------------------------------------------------------------------------------------------------
#Body
data=`test message`
#-----------------------------------------------------------------------------------------------------
                grep "$min_1" $log_er | grep limiting | awk '{print $16}' | sed 's/,/ /g' | while read line; do
                        if [[ $line =~ ^domain1.com ]] ;then
                                full_line=`grep "$min_2" $log_2 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        fi
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                        elif [[ $line =~ ^domain2.com ]] ;then
                                full_line=`grep "$min_2" $log_2 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                         elif [[ $line =~ ^domain3.com ]] ;then
                                full_line=`grep "$min_2" $log_3 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                        elif [[ $line =~ ^domain4.com ]] ;then
                                full_line=`grep "$min_2" $log_4 | awk '{print $3}' | sort | uniq -c | sort -n `
                                full_line_s=`echo "$full_line" |  awk '{print $1}'`
                                for line in $full_line_s
                        do
                                check=`echo "$line"`
                #check limits
                        if (( $check > $thr ))
                then
                        echo "Some text: $data"|mail -s "Some text on $host" $mailbox
                        fi
#-----------------------------------------------------------------------------------------------------
                else
                        break;
        fi
                done

По частям скрипт работает, но связать все в один не получатся, особенно if fi не могу понять как работает, если там не один цикл, а четыре. Плюс еше if fi из шага 3 там мешаются. Короче завис я( Помогите пожалуйста, буду очень благодарен.
Спасибо.

21

ЕМНИП в centos 6 по дефолту rsyslog, который имеет модуль ommail, с помощью которого можно отсылать на почту нужные сообщения в зависимости от событий, типа событийи т.д. От скриптов можно послностью отказаться.