Код:
#!/bin/bash
# v2
# Переменные {{{
# Временные переменные.
declare -i i=0
declare -i j=0
declare s=""
# Отладка (битовое ИЛИ для включения нескольких сразу)
i=1
declare -r -i debug_input_parse=i && ((i<<=1))
declare -r -i debug_init_node_t=i && ((i<<=1))
declare -r -i debug_select_node=i && ((i<<=1))
declare -r -i debug_check_node=i && ((i<<=1))
declare -r -i debug_all=-1
declare -r -i debug=0
# Для печати ошибок/предупреждений/инфо
declare -r PS_E="${0##*/}: Error"
declare -r PS_W="${0##*/}: Warning"
declare -r PS_I="${0##*/}: Info"
# Список телефонов
declare -r -a telephone=(
01
02
03
)
# Для "текущих" значений в циклах
declare tel=""
declare msg=""
declare tmp_path="."
# Защита от опечаток (несколько слешей будем считать уже не опечаткой)
tmp_path="${tmp_path%/}"
declare -r tmp_path
# Переменные для вычисления "а не пора ли отправлять сообщение?"
declare -i cur_time=0
declare -i fail_time=0
declare -i delta_time=0
# Принцип хранения данных аналогичен (не совсем) такой структуре {{{
#
# struct node_t {
# int delay; // задержка отправки сообщения
# struct list_t list; // список узлов для этой задержки
# };
#
# (.list теперь не указатель, в отличие от первой версии). Как и в 1-ой
# версии, узлы, имеющие одинаковую задержку для отправки сообщений,
# содержаться в одном объекте типа 'struct node_t'.
#
# Как это все реализовано здесь:
#
# Все объекты последовательно записаны в массив
#
# node_t__data[] (аналогия с памятью)
#
# и смещение до начала каждого объекта записано в массиве
#
# node_t__off[] (аналогия с массивом указателей 'struct node_t **')
#
# Смещение элементов объекта (.delay и .list) от его начала записано в
# переменных
#
# node_tDelay
# node_tList
#
# В отличие от 1-ой версии, кроме другого принципа хранения данных, здесь уже
# объекты не имеют имен (т.е к ним можно обратиться только по индексу в
# массиве - аналогия с 'struct node_t *').
#
# Вот картинка
#
# node_t__data[]
# ------============
# node_t__off[] | I I
# I===========I | I I
# I I | I I
# I ... I | I I
# I-----------I v I I
# I смещение I------------> -----I----------I------------ объект А
# I объекта А I I I | | node_tDelay
# I-----------I I I | v
# I смещение I------+ I----------I-|---
# I объекта Б I | I задержка I | node_tList
# I-----------I | I I v
# I I | I----------I---
# I I | I список I
# I I | I узлов I
# I I | I ... I
# I I +-----> -----I----------I------------- объект Б
# I I | I ... I
#
# (на самом деле, node_tDelay == 0, а не так, как нарисовано на картинке)
#
# }}}
# Смещения элементов структуры от начала самой структуры.
i=0
declare -r -i node_tDelay=$((i++)) # смещение элемента .delay (размер == 1)
declare -r -i node_tList=$((i++)) # смещение элемента .list (размер
# неопределен)
declare -r -i minsize_node_t=$i # минимальный размер правильного объекта
i=0
# Для "текущего" объекта в циклах
declare node_t="" # имя (указатель) текущего объекта
declare -i sizeof_node_t=0 # размер текущего объекта.
declare -i node_t__delay=0 # значение элемента .delay текущего объекта
declare -i node_t__list_start=0 # индекс в node_t__data[], где начинается
# элемент .list текущего объекта
declare -i node_t__list_end=0 # индекс в node_t__data[], где кончается
# элемент .list текущего объекта (последний
# элемент .list-а находится по предыдущему
# индексу)
declare node="" # текущий элемент в .list
# Определения объектов.
### Редактируется пользователем (начало).
# Определения не соответствующие по форме (например, без использования
# '[node_tDelay]=..' и тд) могут обойти проверки на ошибки, поэтому лучше
# писать, как в примере -)
declare -a node_t_A=(
[node_tDelay]='0'
[node_tList]='A1' 'A2'
)
declare -a node_t_B=(
[node_tDelay]='20'
[node_tList]='B1' 'B2' 'B3'
)
# список всех объектов (объекты, не указанные здесь, игнорируются).
declare -a node_t__obj=(
node_t_A
node_t_B
)
### Редактируется пользователем (конец)
# Определения внутренней структуры хранения.
if declare -p node_t__off node_t__data >/dev/null 2>&1; then
echo "${PS_E}: one of internal variable names - 'node_t__off' or 'node_t__data' - already used"
exit -1
fi
# Все объекты записаны сюда последовательно.
declare node_t__data=( )
# Смещения в node_t__data[] до начала соответствующего объекта.
declare -i node_t__off=( 0 )
# }}}
# Инициализация внутренней структуры. {{{
# Копируем (а заодно проверяем) данные из объектов, определенных
# пользователем, в node_t__data[] и записываем соответствующие смещения в
# node_t__off[]. Скопированы будут только объекты, указанные в node_t__obj[].
# Последовательность объектов в node_t__data[] будет такая же, как в
# node_t__obj[]. После завершения копирования node_t__obj[] и все объекты,
# указанные в нем, будут удалены. Т.е далее получить доступ к объектам можно
# будет _только_ через node_t__off[] и node_t__data[].
# FIXME: check type of user-defined variables.
# '-r' flag will be detected during `unset`. '-a' flag is implicitly checked
# through number of elements in user-defined object. Probably, that's enough.
# FIXME: check content of user-defined objects (.delay is integer, .list
# containt only not empty elements).
# We really need this?
if [ "x${node_t__obj[*]}" == "x" ]; then
echo "${PS_I}: Nothing to be done, no objects defined."
exit 0
fi
i=0
for node_t in "${node_t__obj[@]}"; do
if ! declare -p ${node_t} >/dev/null 2>&1; then
echo "${PS_W}: object '$node_t' is not defined, skipped."
continue
fi
eval "sizeof_node_t=\${#$node_t[*]}"
if ((sizeof_node_t < minsize_node_t)); then
echo "${PS_W}: size of element '$node_t' is lesser, than minimal, skipped."
continue
fi
node_t__off[++i]=$((node_t__off[i] + sizeof_node_t))
((debug & debug_init_node_t)) \
&& echo "Init: object '$node_t', sizeof = '$sizeof_node_t'" \
&& echo " offset = '${node_t__off[i]}', index = '$i'"
eval "
node_t__data=(
\"\${node_t__data[@]}\"
\"\${$node_t[@]}\"
)
"
if ! unset $node_t; then
echo "${PS_E}: can not unset variable '$node_t'"
exit -1
fi
done
((debug & debug_init_node_t)) \
&& echo "Init: completed, environment" \
&& declare -p node_t__off node_t__data \
&& (
IFS=','
declare -p "${node_t__obj[@]}" >/dev/null 2>&1 \
|| echo "${node_t__obj[*]} unset"
)
if ! unset node_t__obj; then
echo "${PS_E}: can not unset variable 'node_t__obj'"
exit -1
fi
# }}}
# Функции {{{
func_check_node() {
# Параметры:
# 1 - node
# Для отладки:
read -p'->' -n1 -r rep
return $rep
/bin/ping -c 5 $1 > /dev/null 2> /dev/null
return $?
}
func_send_msg() {
# Параметры:
# 1 - telephone
# 2 - message
# Для отладки:
echo - $1 - $2
return $?
/usr/bin/scmxx --device=/dev/ttyACM0 --send --sms --direct --number=$1 --text="$2"
return $?
}
# }}}
# Последний элемент в node_t__off[] - это смещение на начало пустой области в
# node_t__data[], поэтому его пропускаем.
for ((i = 0; i < (${#node_t__off[*]} - 1); i++)); do
node_t__delay="${node_t__data[node_t__off[i] + node_tDelay]}";
node_t__list_start=$((node_t__off[i] + node_tList));
node_t__list_end=$((node_t__off[i + 1]));
((debug & debug_select_node)) \
&& echo "Select: object [$i] with offset '${node_t__off[i]}'" \
&& echo " delay = '$node_t__delay', list_start = '$node_t__list_start', list_end = '$node_t__list_end'"
for ((j = node_t__list_start; j < node_t__list_end; j++)); do
node=${node_t__data[j]};
node_file="$tmp_path/$node"
((debug & debug_select_node)) \
&& echo " Select node from .list: '$node' with path '$node_file'"
func_check_node "$node"
ret=$?
if ((ret)); then
((debug & debug_check_node)) \
&& echo " Node '$node' down"
cur_time="$(date +%s)"
if [ -e "$node_file" ]; then
# Узел уже "лежал" в предыдущую проверку.
fail_time="$(<"$node_file")"
delta_time=$((cur_time - fail_time))
((debug & debug_check_node)) \
&& echo " over $delta_time seconds ($cur_time, $fail_time)"
if ((delta_time > node_t__delay)); then
# Сообщение об ошибке, только если узел лежит дольше, чем
# ему можно (элемент .delay). Время падения сбрасываем в
# текущее, чтобы сообщения не отправлялись каждую
# следующую проверку.
[ -z "$errors" ] \
&& errors="Down: $node" \
|| errors="$errors, $node"
echo "$cur_time" >"$node_file"
# Сохраняем _предыдущее_ время модификации, - чтобы потом
# определить было ли отправлено хотя бы одно сообщение.
touch -m --date="@$fail_time" "$node_file"
((debug & debug_check_node)) \
&& echo " Timeout reached, mark as error: '$errors'" \
&& echo " New fail time: '$(<"$node_file")'" \
&& echo " Previous fail time: '$(stat -t -c "%Y" "$node_file")'"
fi
else
# Узел упал в первый раз. Записываем время, чтобы дальше
# считать сколько он уже лежит. Если задержка 0, отправляем
# сообщение сразу.
echo "$cur_time" >"$node_file"
((debug & debug_check_node)) \
&& echo " for the first time"
if ((!node_t__delay)); then
[ -z "$errors" ] \
&& errors="Down: $node" \
|| errors="$errors, $node"
((debug & debug_check_node)) \
&& echo " Report immediately, mark as error: '$errors'"
fi
fi
else
((debug & debug_check_node)) \
&& echo " Node '$node' up"
if [ -e "$node_file" ]; then
# fail_time - время отправки сообщения _перед_ предыдущим,
# если оно было, либо время первого падения интерфейса.
cur_time="$(date +%s)"
fail_time="$(stat -t --format="%Y" "$node_file")"
delta_time=$((cur_time - fail_time))
((debug & debug_check_node)) \
&& echo " but was down over $delta_time seconds"
if ((delta_time > node_t__delay)); then
# Если разница между текущем временем и временем
# модификации больше допустимой, сообщения (хотя бы одно)
# отправлено было.
[ -z "$fixed" ] \
&& fixed="Fixed: $node" \
|| fixed="$fixed, $node"
((debug & debug_check_node)) \
&& echo " Error message was sent, mark as fixed: '$fixed'"
fi
fi
/bin/rm -f "$node_file"
fi
done
done
for msg in "$errors" "$fixed"; do
[ -z "$msg" ] && continue
for tel in "${telephone[@]}"; do
func_send_msg "$tel" "$msg"
done
done
exit 0
переделанный скрипт, но неработает....шелописатели, помогите поправить
_________________
Код:
Клиент: вер. 6.2.714 / 25.05.2015 17:27:15
os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_45
Сервер: вер. 6.2.881 / 22.05.2015 17:56:55
os: Linux; java: Java HotSpot(TM) 64-Bit Server VM, v.1.8.0_45
Помощь по администрированию bgbilling в jabber конференции или Группа в telegramСтиль программирования - пьяный мастерстер
Разработка мобильных приложений