Тема: ошибки в скриптах wialon-service-check.sh
Сегодня наконец-то наше время разобраться почему cron присылает жалобы на почту при запланированном выполнении этих скриптов. Жалобы имели вид:
/wialon/wialon-service-check.sh: line 3: wialon-include-check.sh: No such file or directory
Поначалу я вообще ничего не понимал, почему вылазиет эта ошибка. Все файлы на месте, запускал скрипт вручную из midnight commander'а, все было в порядке.
Потом осенило, что во всем виновата переменная PATH и то, что не хватает ./ перед именем скрипта (т.е. надо было ./wialon-include-check). Но и это ситуацию не исправило а man bash подтвердил, что в конце концов source script.sh в конце концов все-таки поищет в текущем каталоге указанный скрипт.
Далее методом проб и ошибок выяснил, что текущим каталогом при выполнении скрипта будет не каталог в котором он находится, а каталог вызывающего процесса. Т.е. если я находился в mc в каталоге /wialon то запуская скрипт, конструкция source wialon-include-check.sh работала т.к. данный скрипт находился в текущем каталоге, а для cron'а, текущий каталог которого явно не /wialon, а какой-нибудь там /usr/sbin, получалась ошибка из-за того, что файла wialon-include-check в /usr/sbin просто напросто нет.
Исправил все пути на абсолютные т.е : source /wialon/wialon-include-check и посчитал, что дело сделано. Ан нет.
Все равно ноет в логи про ту же самую ошибку no such directory... Начал добавлять в wialon-include-check выводы значений переменный после каждой операции: echo $ROOT, echo $SCRIPT_PATH ... В итоге обнаружил, что вопреки учебникам по программированию на BASH, встроенная переменная $0 возаращает не путь к файлу wialon-include-check.sh а просто 'bash'. По счастливой случайности опеннетовском учебнике по программир. на bash была сноска, что $0 на самом деле устанавливается вызывающим процессом. Т.о. если мы запускаем из командной строки:
user@host $ ./wialon-include-check.sh
$0 = ./wialon-include-check.sh
т.е. выполнение скрипта форкается в отдельный процесс который и будет вызывающим
а если
user@host $source wialon-include-check.sh
$0 = bash
т.к. в данном случае вызывающим процессом будет /bin/bash который будет исполнять скрипт.
Возможно последние тезисы были сформулированны неграмотно, но ps -ejH показывает что по факту так оно и есть.
(в первом случае в иерархии процессов есть процесс с именем скрипта, а во втором случае есть только bash)
Предполагаю, что человек, писавший эти скрипты отлаживал их находясь в директории виалона поэтому об ошибках ему сообщений не было.
Таким образом вместо $0 следует использовать другую встроенную переменную $BASH_SOURCE с ней все работает.
Поэтому предлагаю Gurtam поправить эти скрипты следующим образом (я сделал так, но он не единственный)
wialon-include-check.sh
#!/bin/bash
EMAIL="support@gurtam.com"
TOPIC="Wialon Pro"
SCRIPT_PATH="$BASH_SOURCE"
# Detect base path for service
while true; do
ROOT=${SCRIPT_PATH%/*}
ROOT=`cd "$ROOT";pwd`
cd $ROOT
if [ -d "$ROOT/plugins" ] && [ -d "$ROOT/scripts" ] ; then
break
fi
if [ -L "$SCRIPT_PATH" ]; then
SCRIPT_PATH=`readlink "$SCRIPT_PATH"`
if [ $? != 0 ]
then
echo "Error: Problems with resolving '$SCRIPT_PATH'" | mail -s "$TOPIC" "$EMAIL"
exit -1
else
continue
fi
fi
break
done
а в файлах wialon-db-check.sh; wialon-service-check.sh; wialon-errors-check.sh поправить строчку вызова подпрограммы с использованием абсолютного пути, чтобы не заморачиваться с определением местоположения скриптов:
#!/bin/bash
source /wialon/wialon-include-check.sh
# Stop associated service
if [ -e "$ROOT/adf_script" ]
then
log=`$ROOT/adf_script check`
if [ "$log" != "" ]
then
BASE=`basename $ROOT`
HOST=`hostname`
echo "$BASE($HOST): $log" | mail -s "$TOPIC" "$EMAIL"
fi
fi
Кстати скрипт wialon-check-db.sh вообще пустой, но тем не мене есть в cron-заданиях, может его убрать из дистрибутива? Зато в заданиях отсутствует скрипт wialon-db-check.sh.
В общем хотелось бы услышать мнения более компетентных людей , нежели я, по этому поводу.