Skyb писал(а): ↑16.09.2010 10:41
Несовсем понял как он работает, тоесть просто описать логику работы скрипта..
Вообще, самое лучшее (на мой взгляд) объяснение, как он работает написано в комментах, поэтому все повторять не буду - напишу только основное.
Мой скрипт - это переписанный ваш с другим способом хранения исходных данных (узлов и информации о задержек для отправки) и некоторыми изменениями в алгоритме выбора "отправлять/не отправлять". Он состоит из двух частей: первая часть - реализация выбранной мной схемы хранения. Эта часть может быть легко заменена на любую другую схему хранения, в том числе и более простую (и заменить, возможно, стоит: я выбрал такую схему хранения не потому, что она оптимальна, а потому, что хотел попробовать что получится). Вторая часть - это, собственно, алгоритм отправки. Эти две части независимы друг от друга (и, соответственно, могут быть изменены независимо).
Схема хранения.
Как уже было написано в комментах, я использую аналогию для
Код: Выделить всё
struct node_t {
int delay; // задержка отправки сообщения
struct list_t *list; // список узлов с такой задержкой
};
struct node_t A;
struct node_t B;
...
Детали реализации (даже с картинками ^) есть в комментах. Название node_t, как я немного поздно сообразил, неудачно, тк структура содержит информацию не об одном узле, а о всех узлах с одинаковой задержкой отправки.
Кроме того, если нужно иметь возможность получить доступ к определенному объекту "по имени", то надо определять
т.е в скрипте
Код: Выделить всё
i=0
declare -i node_t_A=$((i++))
declare -i node_t_B=$((i++))
Если же это не нужно (а в данном случае, это скорее всего не нужно), то можем просто использовать массив
т.е в скрипте это
Код: Выделить всё
i=0
declare -i node_t_A=$((i++))
declare -i node_t_B=$((i++))
i=0
declare -a node_t_obj=(
node_t_A
node_t_B
)
можно стереть и просто перебирать все элементы массивов node_tList[] и node_tDelay[] (ну, просто стереть недостаточно - надо будет немного изменить циклы, перебирающие элементы).
Skyb писал(а): ↑16.09.2010 10:41
и ещё где прописывать хосты узлов??
Если ничего не менять в скрипте, то, допустим, у вас следующая конфигурация
Код: Выделить всё
Для узлов A1, A2, A3 - сообщения отправлять сразу
Для узлов B1, B2 - через 30 секунд.
Для узла C1 - через 10 минут.
Тогда узлы A1, A2, A3 будут описаны в объекте A (аналогия struct node_t A), узлы B1, B2 - в объекте B (struct node_t B), узел С - в объекте C (struct node_t C).
Код: Выделить всё
i=0
declare -i node_t_A=$((i++))
declare -i node_t_B=$((i++))
declare -i node_t_C=$((i++))
i=0
и еще массив
Код: Выделить всё
declare -a node_t_obj=(
node_t_A
node_t_B
node_t_C
)
чтобы не перечислять все объекты каждый раз в циклах.
Это аналогия для
Теперь надо проинициализировать.
Задержка отправки
Код: Выделить всё
declare -i -a node_tDelay=(
[node_t_A]=0
[node_t_B]=30
[node_t_C]=600
)
это аналогия для
Списки узлов
Код: Выделить всё
declare -a node_tList=(
[node_t_A]="node_tList_A"
[node_t_B]="node_tList_B"
[node_t_C]="node_tList_C"
)
declare -a node_tList_A=(
'A1'
'A2'
'A3'
)
declare -a node_tList_B=(
'B1'
'B2'
)
declare -a node_tList_C=(
'C1'
)
это аналогия для чего-то такого (не уверен, что ничего не напутал, но смысл понятен, я думаю)
Код: Выделить всё
Как-то определить A1, A2, B1, B2, B3, C1.
...
A.list = (list_t *) malloc (sizeof (struct list_t));
list_t_init(A.list, 3, &A1, &A2, &A3);
B.list = (list_t *) malloc (sizeof (struct list_t));
list_t_init(A.list, 2, &B1, &B2);
C.list = (list_t *) malloc (sizeof (struct list_t));
list_t_init(A.list, 1, &C1);
После строк
Код: Выделить всё
for node in "${node_t__list[@]}"; do
node_file="$tmp_path/$node"
...
реализация схемы хранения заканчивается и начинается алгоритм, определяющий "отпавлять или не отправлять". Переменная node - это имя узла (также, как у вас), а node_file - это временный файл, куда писать время. Проверки пинга и отправку смс я поместил в функции для удобства. Алгоритм "определения отправки" такой:
1. Проверяем что-то (вызывая функцию).
2. Если это что-то возвращает >0, то
2.1 Если файл с временем не существует, создаем и записываем туда текущее время, заодно проверяя если задержки отправки нету (0), то сразу регистрируем ошибку (в переменной errors).
2.2 Если файл с временем существует, то считаем сколько времени прошло с тех пор, как узлу стало плохо.
2.2.1 Если меньше допустимомго, то ошибку не регистрируем (не записываем в errors ничего).
2.2.2 Если больше, то добавляем в errors сообщение, затем обновляем время в файле на текущее (старое время стирается, оно уже не нужно). Если этого не сделать, сообщение об ошибке будет посылаться _каждый_ следующий запуск (если узел все еще лежит). Я думаю, что это неправилно. Затем, время изменения файла выставляем в _прошлое_ время падения. Это нужно, чтобы правильно опеделять было ли отправлено сообщение об ошибке и посылать ли сообщение "Fixed:" (см. ниже).
3. Если вовзращает 0, то
2.1 Если файл с временем существует, считаем разницу между текущим временем и временем модификации файла, чтобы определить нужно ли отпавлять сообщение с "Fixed".
2.1.1 Если меньше допустимого для этого узла времени "лежания", то не отправляем.
2.1.2 Если больше - отправляем.
Удаляем файл в любом случае.
Все временные метки в секундах с 1970-01-01 UTC.
Про определение "было ли отпрвлено сообщение об ошибке".
Картинка..
Код: Выделить всё
прошлое время
падения узла
| Узел "исправился"
| |
v (интервал) v
----+-------------------+--------*
E1 E2 F1
^
|
сообщение об ошибке
отправлено сейчас и это
время записано в файл
(время модификации установлено в E1).
В момент времени F1 в файле записано время E2, и время до следующей отправки еще не истекло. Поэтому, возможны два случая:
- файл был создан в момент времени E2 и сообщение об ошибке отправлено не было.
- файл был создан раньше, сообщение об ошибке уже было отправлено один или больше раз, и время в файле было обновлено (то, что на картинке).
Чтобы различить эти случаи, при обновлении времени в файле (после отправки сообщения) я сбрасываю время модификации на предыдущее время отправки (или время создания, если это первое сообщение об ошибке). Поэтому, получается, что если сообщение еще не было отправлено ни разу,
и сообщение с "Fixed" не посылаем.
Если сообщение было отправлено хотя бы раз,
и надо посылать сообщение с "Fixed".
Skyb писал(а): ↑16.09.2010 10:41
и что значит
Код: Выделить всё
# Для "текущих" значение в цикле
declare tel=""
declare msg=""
эти значения
Первое - это просто временные переменные для чего попало. Второе - ну, как и написано, "индексы" цикла по телефонам и сообщениям.
PS. Думаю это должно быть и так понятно: мой скрипт не будет работать под sh (только bash).
UPD.
Скрипт немного обновлен.