LINUX.ORG.RU
ФорумAdmin

sed замена переменной

 , ,


1

2

Здравствуйте!

Мне нужно парсить файл(FILE): брать оттуда имя пира, IP, по IP узнавать MAC (и сравнивать его с нужным типом оборудования), потом это все записывать в файл(GW_INFO) в виде: $Peer-$GW_IP:$GW_MAC (вот так: [G14448]-192.168.1.223:38:3F:10:04:D4:AC )
Содержимое файла$FILE:
[G13646] type=friend host=192.168.1.234 ] allow=g729 allow=g723 allow=alaw allow=ulaw qualify=yes context=out progressinband=never
[G14408] type=friend host=192.168.1.171 allow=g729 allow=g723 allow=alaw allow=ulaw qualify=yes context=out progressinband=never
[G14408] type=friend ..и т.д. в таком же духе.....
и т.д.

Делаю это все в цикле (для эксперимента вынес sed за цикл)
Проблема с последним: sed'ом заменять переменную $Peer на строку: $Peer-$GW_IP:$GW_MAC
Получается следующее:
1) Файл GW_INFO содержит: (до выполнения следующего пункта):
[G13646]-
[G14408]-
[G14409]-
[G14412]-
[G14448]-

2) После выполнения

sed -i "s/${Peer}/\[${Peer}\]-${GW_IP}:${GW_MAC}/g" /root/GW_INFO 
имею такое:
[[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC36[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC6]-
[[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC0[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC]-
[[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC09]-
[[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC2]-
[[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC[[G14448]]-192.168.1.223:38:3F:10:04:D4:AC]-


Хочу в таком виде:
[G13646]-192.168.1.234:38:3F:10:04:D4:AC
[G14408]-192.168.1.171:38:3F:XX:XX:XX:XX

Теперь вопросы:
-почему при прохождении цикла оно каждый раз записывает одну и ту же переменную ( что не так с алгоритмом?)
-как преобразовать регулярку в sed для моей задачи?

Сам код:

#!/bin/bash
### VARIABLES
FILE=/root/GW_INFO #Destination of the file with GW's MAC-adresses
SIP_CONF=/etc/asterisk/sip.conf
COUNT=0
### END OF VARIABLES
### Block creates file GW_INFO and write to it GW's MAC-adresses getting ip-adresses from sip.conf
if test ! -f $FILE # Use "!" after "test" for test mode
        then
         echo "File GW_INFO exists"
        else
         touch /root/GW_INFO
         echo "File GW_INFO created"
### END of block
         GW_quantity=$(grep -c "\[G....." $SIP_CONF )
         echo "GW counted, quantity = $GW_quantity"
### Creates \n in $File. P.S. rudimentaly for using SED command
### For Sed use "echo -e "\n" >> $FILE" only ( create only 1 line)
        while [ $GW_quantity -ne 0 ]
                 do
                  echo -e "\n" >> $FILE
                  GW_quantity=$[$GW_quantity - 1]
                 done
### END of block
### Parse sip.conf
                while read LINE
                        do
                           # Peer=0
                           # GW_IP=0
                           # GW_MAC=0
                            if [[ $LINE == "[G"* ]];
                             then
                              Peer=0
                              Peer=$LINE
                              let "COUNT = COUNT + 1"
                              echo $Peer
                                 sed -i "${COUNT}a\ $Peer-" /root/GW_INFO
                            fi
                            if [[ $LINE == "host"* ]];
                              then
                                 GW_IP=0
                                 GW_IP=`echo "$LINE" | cut -d= -f2`
                                 echo $GW_IP
                                GW_MAC=`echo $(nmap $GW_IP) | awk -F"MAC Address: " '{print $2}' | grep -v :38 | awk '{print $1}'`
                                echo $GW_MAC                      
                            fi
                       #sed -i "s/${Peer}/${Peer}-${GW_IP}:${GW_MAC}/g" /root/GW_INFO Изначально планировал sed здесь
                done < $SIP_CONF
echo "FOR TEST:"
echo $Peer
echo $GW_IP
echo $GW_MAC
sed -i "s/${Peer}/\[${Peer}\]-${GW_IP}:${GW_MAC}/g" /root/GW_INFO
fi
Заранее спасибо!
P.S. Это мой первый опыт использования bash
P.S.S. Знаю, что на Питоне/Перле и т.д. это можно сделать гораздо красивей



Последнее исправление: kondencator (всего исправлений: 1)

#!/usr/bin/perl

BEGIN { $arpc = {}; }

sub MACOf {
    return '?' unless open($h, 'nmap -sP -n '.shift.' |');
    ($mac) = grep(/^MAC\s+Address:\s+/i, <$h>);
    close($h);
    return '?' unless $mac;
    ($mac) = ($mac =~ /^MAC\s+Address:\s+([\w:]+)/i);
    return $mac ? $mac : '?';
};

next unless ($gw, $rest) = (/^(\[\w+\])\s+(.+)/);
$vars = {}; map { ($n, $v) = (/(\w+)=(.*)/); $vars->{$n} = $v; } grep(/=/, split(/\s+/, $rest));
next unless defined($host = $vars->{'host'});
$mac = defined($arpc->{$host})
    ? $arpc->{$host}
    : $arpc->{$host} = &MACOf($host);
print "$gw-$host:$mac\n";

perl -n script.pl < data.txt

berrywizard ★★★★★
()
Ответ на: комментарий от berrywizard

Спасибо большое за скрипт. С Перлем не знаком :(
Проблема именно в том, чтобы понять как с помощью sed менять строчку по шаблону на переменную ( далее нужно будет изменить в /etc/asterisk/sip.conf IP для определенного пира). Сама задача: отслеживать изменения IP-адресов и потом менять эти айпишники в файле конфигурации Астериск (именно ради этого и мучаюсь с sed). Поменять в строке слово на переменную не трудно, но вот как делать при заполнении файла сообразить не могу....

kondencator
() автор топика

Для начала добавь ключ '-x' к вызываемому скриптом башу что б получилось '#!/bin/bash -x', запусти ещё раз и вдумчиво прочти где и как у тебя переменные выставляются.

manntes-live ★★★
()
Ответ на: комментарий от kondencator

добавь к посту теги asterisk и bash

anonymous
()
Ответ на: комментарий от kondencator

В диалпире для этих шлюзов добавить команды, генерирующие строку «host=ip.ad.dr.es» в где-нибудь «/var/lib/asterisk/mypeers/<имя>.addr», в /etc/asterisk/sip.conf (или где ьам у вас) делаем:


[g1346]
...
#include "/var/lib/asterisk/mypeers/g1346.addr"
...

[g1347]
...
#include "/var/lib/asterisk/mypeers/g1347.addr"
...

После чего в крон раз в час/день/пол-года/пятилетку ставим

asterisk -x «reload sip»

berrywizard ★★★★★
()
Последнее исправление: berrywizard (всего исправлений: 1)
Ответ на: комментарий от manntes-live

добавь ключ '-x' к вызываемому скриптом башу что б получилось '#!/bin/bash -x'

Вот это открытие! Дэбаг для баша (правда не пошаговый, но и то хорошо). Спасибо большое! Сейчас буду разбираться.

kondencator
() автор топика

посмотри что у тебя выдает в таком цикле

while read LINE
do
  echo "$LINE"
  echo
done < $SIP_CONF
если построчно файл читается - добавляй условия и тд и смотри где будет затык.

nerve ★★
()
Ответ на: комментарий от berrywizard

В диалпире для этих шлюзов добавить команды, генерирующие строку «host=ip.ad.dr.es»......

Подумаю над этим методом.
Дело в том, что таких серверов много ( ~100), на каждом менять extensions.conf, sip.conf, править крон, закидывать скрипт задолбусь (последнее два пункта все-равно делать). Да и создание sip.conf&extensions.conf автоматизировано (можно поправить скрипт, но не хотелось бы) Я так думал: заполняем файл с ПИР-IP-МАС, смотрим поменялся ли IP с таким-то МАС"ом, если да - правим sip.conf, зная на каком пире поменялся IP

kondencator
() автор топика
Ответ на: комментарий от berrywizard

Поддерживаю, зачем эта безсмысленная затея?

anonymous
()
Ответ на: комментарий от berrywizard

А что за колдунство с MAC'ами? Зачем оно?

Поддерживаю, зачем эта безсмысленная затея?

Есть SIP-«сервера» к которым подключено по несколько (до 5-ти штук) GSM-шлюзов GoIP ( мануал ), которые регистрируются на сервере в режиме Trunk Gateway Mode. На сервере sip.conf такой:
[G14450]
type=friend
host=192.168.1.172
allow=g729
allow=g723
allow=alaw
allow=ulaw
qualify=yes
context=out
progressinband=never
[G14450]
.. и т.д. и т.п.
Проблема вот в чем: не на всех локациях на роутере привязан IP к МАС'у. Время от времени меняется IP-адрес шлюза и регистрация на SIP-сервере теряется. По возможности привязку IP-MAC на роутерах делаю.
Скрипт: изначально у меня есть данные - пир и его IP. Если поменялся IP-адрес на одном или нескольких шлюзах, то узнать кто из них кто можно только по МАС-адресу, поэтому и хочу записывать в файл информацию ПИР-IP-МАС. Далее сканировать сеть nmap'ом и узнавать IP адрес конкретного MAC-адреса. Потом сравнивать этот IP ( зная его пир со строки ПИР-IP-МАС) с IP, который записан в sip.conf, если не совпадает - менять его ( или sed'ом заменять или, как предлагал berrywizard, #include в sip.conf)
Если есть другие методы решения этой проблемы, буду рад их услышать.
Условия: менять тип подключения с Trunk Gateway Mode на другой не могу. Изменять sip.conf не желательно (окромя как скриптом).
P.S. Тема может тормознуться недели на три, но потом обязательно отпишусь и поделюсь решением (если получиться).

kondencator
() автор топика
Ответ на: комментарий от manntes-live

'#!/bin/bash -x', запусти ещё раз и вдумчиво прочти где и как у тебя переменные выставляются.

Добавил. Добавил несколько cat перед командой
sed -i «s/${Peer}/\[${Peer}\]-${GW_IP}:${GW_MAC}/g» /root/GW_INFO
и после нее. Вот что получилось (под [c_u_t] [/c_u_t] скрыть почему-то не удалось):

+ FILE=/root/GW_INFO
+ SIP_CONF=/etc/asterisk/sip.conf
+ COUNT=0
+ test '!' -f /root/GW_INFO
+ touch /root/GW_INFO
+ echo 'File GW_INFO created'
File GW_INFO created
++ grep -c '\[G.....' /etc/asterisk/sip.conf
+ GW_quantity=2
+ echo 'GW counted, quantity = 2'
GW counted, quantity = 2
+ '[' 2 -ne 0 ']'
+ echo -e '\n'
+ GW_quantity=1
+ '[' 1 -ne 0 ']'
+ echo -e '\n'
+ GW_quantity=0
+ '[' 0 -ne 0 ']'
+ read LINE
+ [[ " == \[\G* ]]
+ [[ " == \h\o\s\t* ]]
+ read LINE
+ [[ [G14722] == \[\G* ]]
+ Peer=0
+ Peer='[G14722]'
+ let 'COUNT = COUNT + 1'
+ echo '[G14722]'
[G14722]
+ sed -i '1a\ [G14722]-' /root/GW_INFO
+ cat ./GW_INFO

[G14722]-



+ [[ [G14722] == \h\o\s\t* ]]
+ read LINE
+ [[ type=friend == \[\G* ]]
+ [[ type=friend == \h\o\s\t* ]]
+ read LINE
+ [[ host=192.168.1.11 == \[\G* ]]
+ [[ host=192.168.1.11 == \h\o\s\t* ]]
+ GW_IP=0
++ echo host=192.168.1.11
++ cut -d= -f2
+ GW_IP=192.168.1.11
+ echo 192.168.1.11
192.168.1.11
++ awk '-FMAC Address: ' '{print $2}'
++ grep -v :38
+++ nmap 192.168.1.11
++ awk '{print $1}'
++ echo Starting Nmap 6.47 '(' http://nmap.org ')' at 2018-01-18 13:44 UTC Nmap scan report for 192.168.1.11 Host is up '(0.00053s' 'latency).' Not shown: 999 closed ports PORT STATE SERVICE 80/tcp open http MAC Address: 38:3F:10:04:B4:26 '(DBL' 'Technology)' Nmap done: 1 IP address '(1' host 'up)' scanned in 3.84 seconds
+ GW_MAC=38:3F:10:04:B4:26
+ echo 38:3F:10:04:B4:26
38:3F:10:04:B4:26
+ cat ./GW_INFO

[G14722]-



+ sed -i 's/[G14722]/[G14722]-192.168.1.11:38:3F:10:04:B4:26/g' /root/GW_INFO
+ cat ./GW_INFO

[[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26]-


+ read LINE
+ [[ disallow=all == \[\G* ]]
+ [[ disallow=all == \h\o\s\t* ]]


Выделил жирным интересующую часть, а именно:
+ cat ./GW_INFO

[G14722]-



+ sed -i 's/[G14722]/[G14722]-192.168.1.11:38:3F:10:04:B4:26/g' /root/GW_INFO
+ cat ./GW_INFO

[[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26[G14722]-192.168.1.11:38:3F:10:04:B4:26]-

Почему оно заменяет [G14722] шесть раз? Дурная идея, но G14722 - шести-значное :)

kondencator
() автор топика

А экранированием кто будет заниматься? sed 's/\[G14722\]/\[G14722\]-192.168.1.11:38:3F:10:04:B4:26/g' В вашем варианте [G14722] в квадратных скобках это перечень возможных символов, именно символов. Далее добавляете ключ g - замена во всех встречающихся случаях, а не только в первом. Вот и результат.

anc ★★★★★
()
Ответ на: комментарий от anc

А экранированием кто будет заниматься?

не будете ли так добры подсказать как экранировать переменную, в составе которой есть символы [ ]? Пробовал раньше с экранированием, тоже не достиг желаемого результата. Вот регулярка:
sed -i «s/${Peer}/\[${Peer}\]-${GW_IP}:${GW_MAC}/g» /root/GW_INFO
где ${Peer} = [G14722]

kondencator
() автор топика
Ответ на: комментарий от anc

В вашем варианте [G14722] в квадратных скобках это перечень возможных символов, именно символов.

Забыл написать. Сейчас вот такой скрипт:

echo $Peer
echo $GW_IP
echo $GW_MAC
cat ./GW_INFO
sed -i "s/${Peer}/${Peer}-${GW_IP}:${GW_MAC}/" /root/GW_INFO
cat ./GW_INFO
Это все внутри цикла выполняется n-раз. Вы правы по поводу замены символов

это перечень возможных символов, именно символов

Дебаг:
Первый проход:

+ echo '[G13646]'
[G13646]
+ echo 192.168.1.234
192.168.1.234
+ echo 38:3F:10:04:AD:86
38:3F:10:04:AD:86
+ cat ./GW_INFO
 [G13646]-
+ sed -i 's/[G13646]/[G13646]-192.168.1.234:38:3F:10:04:AD:86/' /root/GW_INFO
+ cat ./GW_INFO
 [[G13646]-192.168.1.234:38:3F:10:04:AD:8613646]-
Такой вариант вполне устраивает, а вот второй проход цикла:
+ echo '[G14408]'
[G14408]
+ echo 192.168.1.171
192.168.1.171
+ echo 38:3F:10:04:D4:A8
38:3F:10:04:D4:A8
+ cat ./GW_INFO
 [[G13646]-192.168.1.234:38:3F:10:04:AD:8613646]-
 [G14408]- # По идее должно заменить только эту строку (!)
+ sed -i 's/[G14408]/[G14408]-192.168.1.171:38:3F:10:04:D4:A8/' /root/GW_INFO
+ cat ./GW_INFO
 [[[G14408]-192.168.1.171:38:3F:10:04:D4:A813646]-192.168.1.234:38:3F:10:04:AD:8613646]- # Замена первой строки тоже
 [[G14408]-192.168.1.171:38:3F:10:04:D4:A814408]- 
После него первая запись заменена новыми значениями. При третьем и т.д. проходах такая же ситуация. Вы правы, нужно переделать регулярку под замену не символов, а значения. Но вот как это сделать, не соображу.

kondencator
() автор топика
Ответ на: А экранированием кто будет заниматься? от kondencator

Что-то типа sed -r 's/(\[|\])/\\\1/g' остальные спецсимволы по списку разделенные or | в первом выражении добавляйте по вкусу.

Peer=$(echo '[G13646]' | sed -r 's/(\[|\])/\\\1/g'); echo $Peer

\[G13646\]

anc ★★★★★
()
Последнее исправление: anc (всего исправлений: 3)
Ответ на: комментарий от anc

Peer=$(echo '[G13646]' | sed -r 's/(\[|\])/\\\1/g'); echo $Peer

Спасибо! Так работает. Вот скрипт:

Peer=$(echo $Peer | sed -r 's/(\[|\])/\\\1/g')
echo $Peer
echo $GW_IP
echo $GW_MAC
cat ./GW_INFO
sed -i "s/${Peer}-/${Peer}-${GW_IP}_${GW_MAC}/" /root/GW_INFO
cat ./GW_INFO
А вот вывод:

++ echo '[G14408]'
++ sed -r 's/(\[|\])/\\\1/g'
+ Peer='\[G14408\]'
+ echo '\[G14408\]'
\[G14408\]
+ echo 192.168.1.171
192.168.1.171
+ echo 38:3F:10:04:D4:A8
38:3F:10:04:D4:A8
+ cat ./GW_INFO
[G13646]-192.168.1.234_38:3F:10:04:AD:86
[G14408]-
+ sed -i 's/\[G14408\]-/\ [G14408\]-192.168.1.171_38:3F:10:04:D4:A8/' /root/GW_INFO
+ cat ./GW_INFO
[G13646]-192.168.1.234_38:3F:10:04:AD:86
[G14408]-192.168.1.171_38:3F:10:04:D4:A8

kondencator
() автор топика
Ответ на: комментарий от anc

Ребята, опять нужна Ваша помощь. Скрипт работает, но нужно создать функцию. Видел много вариантов объявления функции, остановился на следующем:

sip () {
                while read LINE
                        do
                            if [[ $LINE == "[G"* ]];
                             then
                              Peer=0
                              Peer=$LINE
                              let "COUNT = COUNT + 1"
                              echo $Peer
                                 sed -i "${COUNT}a\ $Peer-" $FILE
                            fi
                            if [[ $LINE == "host"* ]];
                                 then
                                 GW_IP=0
                                 GW_IP=`echo "$LINE" | cut -d= -f2`
                                 echo $GW_IP
                GW_MAC=`echo $(nmap $GW_IP) | awk -F"MAC Address: " '{print $2}' | grep -v :38 | awk '{print $1}'`
                                echo $GW_MAC
                                Peer=$(echo $Peer  | sed -r 's/(\[|\])/\\\1/g'); echo $Peer
                                echo $GW_IP
                                echo $GW_MAC
                                cat ./GW_INFO
                                sed -i "s/${Peer}-/${Peer}-${GW_IP}_${GW_MAC}/" $FILE
                                cat ./GW_INFO
                            fi
 done < $SIP_CONF
}
Вызываю ее потом (функция объявлена выше, чем эта часть кода):
if [ "$GW_IP" = "$GW_IP_FILE" ]
   then
    echo "GW" $GW_Peer "IP matched, nothing to do. SBO IP =" $SBO_IP
   else
    echo "GW" $GW_Peer "IP mismatch. Current GW IP =" $GW_IP ".IP was" $GW_IP_FILE ".Changing in sip.conf"
    sed -i "s/host=$GW_IP_FILE/host=$GW_IP/" $SIP_CONF
    sip
  fi
Получаю в результате:

GW [G13646] IP mismatch. Current GW IP = 192.168.1.234 .IP was >192.168.1.235 .Changing in sip.conf
./GW_Check.sh: line 71: sip: command not found

Вот это и тревожит: ./GW_Check.sh: line 71: sip: command not found
Перепробовал варианты объявления функции:
function sip { }
fucntion sip () { }
Вызывал тоже по-разному: sip(), sip. Тот же результат.
Версия Линукса:
root@raspberrypi:~# cat /proc/version
Linux version 4.4.13-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611) ) #894 SMP Mon Jun 13 13:13:27 BST 2016
root@raspberrypi:~# lsb_release -a
No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 8.0 (jessie) Release: 8.0 Codename: jessie
root@raspberrypi:~# cat /etc/*-release
PRETTY_NAME=«Raspbian GNU/Linux 8 (jessie)» NAME=«Raspbian GNU/Linux» VERSION_ID=«8» VERSION=«8 (jessie)» ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs" Версия bash:
root@raspberrypi:~# bash --version
GNU bash, version 4.3.30(1)-release (arm-unknown-linux-gnueabihf) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

Подскажите, пожалуйста, как правильно вызывать и объявлять функцию в моем случае.
Заранее спасибо!

kondencator
() автор топика
Ответ на: комментарий от nerve

Спасибо за ответы.
Сейчас скрипт работает в таком виде:

#!/bin/bash
##### VARIABLES
FILE=/root/GW_INFO #Destination of the file with GW's MAC-adresses
SIP_CONF=/etc/asterisk/sip.conf
COUNT=0
FLAG=0
##### END OF VARIABLES
##### FUNCTIONS
# my_sip  # Parse sip.conf and refresh information in GW_INFO file
##### END OF FUNCTIONS
         GW_quantity=$(grep -c "\[G....." $SIP_CONF )
         echo "GW counted, quantity = $GW_quantity"
##### Parse sip.conf function
function my_sip {
             #   echo "FLAG =" $FLAG
#               if [ $FLAG -eq 1 ]
 #                then
                rm ./GW_INFO
                touch /root/GW_INFO
         echo "File GW_INFO created"
               echo -e "\n" >> $FILE
                while read LINE
                        do
                            if [[ $LINE == "[G"* ]];
                             then
                              Peer=0
                              Peer=$LINE
                              let "COUNT = COUNT + 1"
                                 sed -i "${COUNT}a\ $Peer-" $FILE
                            fi
                            if [[ $LINE == "host"* ]];
                                 then
                                 GW_IP=0
                                 GW_IP=`echo "$LINE" | cut -d= -f2`
                GW_MAC=`echo $(nmap $GW_IP) | awk -F"MAC Address: " '{print $2}' | grep -v :38 | awk '{print $1}'`
                                Peer=$(echo $Peer  | sed -r 's/(\[|\])/\\\1/g');
                                sed -i "s/${Peer}-/${Peer}-${GW_IP}_${GW_MAC}/" $FILE
                            fi
 done < $SIP_CONF
#fi
}
my_sip

##### RASPBERRY IP-ADRESS $SBO_IP
SBO_IP=`ip -4 -o address show eth0 | awk '{print $4}' | cut -d '/' -f 1`
echo "SBO IP - $SBO_IP"
##### SCAN NMAP AND COMPARE MAC AND IP WITH GW_INFO
NMAC=`nmap -sP $SBO_IP/24`
#echo $NMAC
while read LINE
 do
  GW_Peer=`echo $LINE | cut -d '-' -f 1`
  GW_MAC=`echo $LINE | cut -d '_' -f 2`
#  echo $GW_MAC
  GW_IP=`echo $NMAC |awk -F $GW_MAC '{print $1}' |awk -F "for" '{print $NF}' |awk -F " Host" '{print $1}' |cut -d ' ' -f 2 `
  echo $GW_IP
  GW_IP_FILE=`echo $LINE | cut -d '-' -f 2 | cut -d '_' -f 1`
  echo $GW_IP_FILE
  if [ "$GW_IP" = "$GW_IP_FILE" ]
   then
    echo "GW" $GW_Peer "IP matched, nothing to do. SBO IP =" $SBO_IP
   else
    echo "GW" $GW_Peer "IP mismatch. Current GW IP =" $GW_IP ".IP was" $GW_IP_FILE ".Changing in sip.conf"
    sed -i "s/host=$GW_IP_FILE/host=$GW_IP/" $SIP_CONF
#    FLAG=1
   # my_sip
    asterisk -x 'sip reload'
  fi
done < $FILE
Функция вызывается, все норм, но нужно его еще доделать, т.к. при переделке для работы с функцией я поменял логику и теперь вылазить одна неприятная бага. В понедельник займусь и скину рабочий вариант.
Под тэг cut нельзя код прятать?

kondencator
() автор топика
Ответ на: комментарий от kondencator

Под тэг cut нельзя код прятать?

Нет. Это только для

Парный тег [cut] для создания спойлера с целью сокращения занимаемого места на главной странице и в ленте.

anc ★★★★★
()
Ответ на: комментарий от anc

Наконец-то дописал этот скрипт. Как и обещал, выкладываю результат.
Для работы необходимо:
- Правильно настроить sip.conf, проверить зарегались ли пиры на астере ( по этим айпишникам программа вычислит MAC-адреса шлюзов)
- На всякий случай изменить пользователя для скрипта и предоставить права: chown root:root ./GW_Check.sh chmod 007 ./GW_Check.sh
- Перед первым запуском проверить, существует ли файл ./GW_INFO. Если да, удалить его.
Как проверить:
1)Удалить ./GW_INFO, запустить скрипт ./GW_Check.sh.
2) Зайти в sip.conf, изменить строку host=xxx.xxx.xxx.xxx.
3) Запустить скрипт ./GW_Check.sh.
4) Посмотреть sip.conf, убедиться что вернуло значение IP обратно
Примечания:
1) Во время работы выводится сообщение:

Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

Это нормально, grep “встречает” пустую строку в начале и конце файла
2) Проверка “реальных” IP-адресов производиться по MAC-адресам. При смене оборудования, необходимо удалить файл GW_INFO и запустить скрипт заново.
Как оно работает?
1) При первом запуске парсит sip.conf, берет оттуда «нормальные» IP-адреса оборудования (по которым можно узнать MAC-адреса). Заполняет файл GW_INFO данными в виде Peer-IP_MAC
2) Узнает IP-адрес сервера, сканирует nmap'ом сеть и узнает IP-адреса VoIP оборудования по ранее записными MAC-адресами с файла GW_INFO
3) Сравнивает этот IP-адрес с IP пира в файле sip.conf. Если IP железки поменялся (DHCP mode на роутере), заменяет IP пира в sip.conf.
4) Делает перечитку sip.conf Астера
Всем спасибо за помощь!
P.S. Можно увеличить быстродействие, если в функции fill_GW_INFO один раз делать nmap и выбирать оттуда МАС-адреса. Увеличит быстродействие в (N-1) раз, где N - кол-во VoIP-оборудования в sip.conf
Сам код (осторожно bash! ;) ) Заранее извиняюсь за такой дибильный вид, копировал с vim.


#!/bin/bash
##### VARIABLES
GW_SIP_INFO=/root/GW_SIP_INFO #Temporary file
FILE=/root/GW_INFO #Destination of the file with GW's MAC-adresses
SIP_CONF=/etc/asterisk/sip.conf
SIP_BACKUP=/etc/asterisk/sip_backup.conf
COUNT=0
##### END OF VARIABLES
##### FUNCTIONS
# create_GW_INFO    # Create GW_INFO file and start fill_GW_INFO function
# fill__GW_INFO    # Parse sip.conf and write information in GW_INFO file once. Use with correct sip.conf !!!
# create_fill_GW_INFO   # Parse sip.conf and refresh information in GW_SIP_INFO file (tmp file with info from sip.conf)
##### END OF FUNCTIONS
         GW_quantity=$(grep -c "\[G....." $SIP_CONF )
         echo "GW counted, quantity = $GW_quantity"
##### Parse sip.conf function
function create_GW_INFO {
                rm $FILE
                touch $FILE
                echo "File GW_INFO was removed and created again. Filling GW_INFO in progress"
                echo -e "\n" >> $FILE
                fill_GW_INFO
                echo "File GW filled"
                cat $FILE
}
function fill_GW_INFO {
                while read LINE
                        do
                            if [[ $LINE == "[G"* ]];
                             then
                              Peer=0
                              Peer=$LINE
                              let "COUNT = COUNT + 1"
                                 sed -i "${COUNT}a\ $Peer-" $FILE
                            fi
                            if [[ $LINE == "host"* ]];
                                 then
                                 GW_IP=0
                                 GW_IP=`echo "$LINE" | cut -d= -f2`
                GW_MAC=`echo $(nmap $GW_IP) | awk -F"MAC Address: " '{print $2}' | grep -v :38 | awk '{print $1}'`
                                Peer=$(echo $Peer  | sed -r 's/(\[|\])/\\\1/g');
sed -i "s/${Peer}-/${Peer}-${GW_IP}_${GW_MAC}/" $FILE
                            fi
 done < $SIP_CONF
}
function fill_GW_SIP {
 rm $GW_SIP_INFO
 touch $GW_SIP_INFO
                echo "File GW_SIP_INFO was removed and created again. Filling GW_SIP_INFO in progress"
                echo -e "\n" >> $GW_SIP_INFO
                GCOUNT=0
               while read LINE
                        do
                            if [[ $LINE == "[G"* ]];
                             then
                             GPeer=0
                             GPeer=$LINE
                              let "GCOUNT = GCOUNT + 1"
                                 sed -i "${GCOUNT}a\ $GPeer-" $GW_SIP_INFO
                            fi
                            if [[ $LINE == "host"* ]];
                                 then
                                 GGW_IP=0
                                 GGW_IP=`echo "$LINE" | cut -d= -f2`
                               GPeer=$(echo $GPeer  | sed -r 's/(\[|\])/\\\1/g');
                                sed -i "s/${GPeer}-/${GPeer}-${GGW_IP}/" $GW_SIP_INFO
                            fi
 done < $SIP_CONF
}

if test -f $FILE # Use "!" after "test" for test mode
        then
         echo "File GW_INFO exists"
         fill_GW_SIP
        else
        fill_GW_SIP
        create_GW_INFO
fi
##### RASPBERRY IP-ADRESS $SBO_IP
SBO_IP=`ip -4 -o address show eth0 | awk '{print $4}' | cut -d '/' -f 1`
echo "SBO IP - $SBO_IP"
##### SCAN NMAP AND COMPARE MAC AND IP WITH GW_INFO
NMAC=`nmap -sP $SBO_IP/24`
while read LINE
 do
  GW_Peer=`echo $LINE | cut -d '-' -f 1`
  GW_MAC=`echo $LINE | cut -d '_' -f 2`
  GW_IP_REAL=`echo $NMAC |awk -F $GW_MAC '{print $1}' |awk -F "for" '{print $NF}' |awk -F " Host" '{print $1}' |cut -d ' ' -f 2 `
 GWPeer=$(echo $GW_Peer  | sed -r 's/(\[|\])/\\\1/g');
 GW_IP_FILE=`cat $GW_SIP_INFO | grep $GWPeer | cut -d '-' -f 2 | cut -d '_' -f 1`
 echo $GW_IP_FILE
  if [ "$GW_IP_REAL" = "$GW_IP_FILE" ]
   then
    echo "GW" $GW_Peer "IP matched, nothing to do. SBO IP =" $SBO_IP
   else
if test -f $SIP_BACKUP
        then
         rm /etc/asterisk/sip_backup.conf
cp /etc/asterisk/sip.conf /etc/asterisk/sip_backup.conf
echo "Backup file: /etc/asterisk/sip_backup.conf"
        else
cp /etc/asterisk/sip.conf /etc/asterisk/sip_backup.conf
echo "Backup file: /etc/asterisk/sip_backup.conf"
fi
  echo "GW" $GW_Peer "IP mismatch. Current GW IP =" $GW_IP_REAL ".IP was" $GW_IP_FILE ".Changing in sip.conf"
   sed -i "s/host=$GW_IP_FILE/host=$GW_IP_REAL/" $SIP_CONF
   asterisk -x 'sip reload'
  fi
done < $FILE

kondencator
() автор топика
Ответ на: комментарий от kondencator

Во время работы выводится сообщение:
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
Это нормально, grep “встречает” пустую строку в начале и конце файла

Это не нормально. Пропустить пустые не судьба?
А то привыкните к ошибкам, а они потом оказываются уже «не задокументированными» :)

anc ★★★★★
()
Ответ на: комментарий от anc

Согласен что это не правильно. Надоел мне этот bash, поэтому оставляю «как есть», если захочу переделать, тогда уж лучше на Python'е, как раз мотивация будет ))

kondencator
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.