LINUX.ORG.RU

Проверка правильности выполнения команды в bash

 


0

1

Есть выходные данные с UPS - подключён ли он к сети или нет. Нужен скрипт, который будет ежеминутно проверять вывод статуса UPS. Если статус ONLINE, то всё в порядке. Если статус OFFLINE - через 10 минут необходимо выполнить команду shutdown

Какие варианты пока пришли мне:

1. Засунуть скрипт в cron, и выполнять раз в минуту. Если статус плохой, отправить команду запуска другого скрипта, который со sleep'ом 10 минут ещё раз проверит статус, и если всё также плохо, от'shutdown'ит машину.

2. Скрипт проводит ежеминутную проверку и при обнаружении проблемы выводит единичку. Через минуту - следующую единичку суммирует к первой. При накоплении десяти единичек, выводит машину в shutdown.

Это на уровне логики. Какими командами это реализовать:

1. Проверяем статус UPS (upsc ups@localhost ups.status), если вывод равен OL CHRG - UPS подключен, вывод 0, если вывод равен OB DISCHRG LB - UPS без питания - вывод 1.

#!/bin/bash
stat=$(upsc ups@localhost ups.status) # 1. Вывести статус подключения UPS к сети, присвоить переменную stat
if [[ $stat = OB DISCHRG LB]] # 2. Если значение переменной равно  OB DISCHRG LB
then 
    echo (i=1) # Вывести единицу
fi

Проверила, не пойму как вывести 1 с присвоением переменной i

2. Ставим счетчик на выведенные единицы, и когда счетчик насчитает 10 единиц, т.е. питание не восстановится за 10 минут, выполнить команду отключения компа:

for ((i=1; i < 10; i++))
do
echo $i
sleep 60
done
shutdown now

Если питание восстановилось за это время и вместо единицы получен ноль, то обнулить счетчик.

Как это скрестить?

Какими командами это реализовать

Нихрена не понял, у вас как-то всё наизнанку. Зачем при проверки статуса UPS что-то куда-то выводить? Делайте бесконечный цикл, в нем проверяйте статус UPS и конструкцией if then else либо инкрементируйте i, либо обнуляйте i. А следом проверяйте что i меньше 10, иначе делайте shutdown. Ну и sleep 60 в конце цикла.

mky ★★★★★
()

Если я правильно понял поставленную задачу, то вот черновой вариант на коленке.

!#/bin/bash

while :
do
	sleep 60
	if [ "$(upsc ups@localhost ups.status)" = "OB DISCHRG LB" ]; then
		sleep 600
		if [ "$(upsc ups@localhost ups.status)" = "OB DISCHRG LB" ]; then
			shutdown now
		fi
	fi
done
Kron4ek ★★★★★
()

if [[ $stat = OB DISCHRG LB]]

В кавычки. А если stat может оказаться неопределен - то ещё добавить костыль-довесок:

if [[ "x$stat" = "xOB DISCHRG LB"]]

Скрипт проводит ежеминутную проверку и при обнаружении проблемы выводит единичку. Через минуту - следующую единичку суммирует к первой. При накоплении десяти единичек, выводит машину в shutdown.

Не десяти единичек, а десяти единичек подряд.

Примерно так.

count=0
while true
do
  stat=$(upsc ups@localhost ups.status)
  if [ "x$stat" = "xOB DISCHRG LB"]
  then
    count=$((count+1))
  else
    count=0
  fi
  [ $count -gt 9 ] && shutdown
  sleep 60
done

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

В кавычки. А если stat может оказаться неопределен - то ещё добавить костыль-довесок

Но там же [[, а не [. Так что в кавычки, вроде, нужно брать только OB DISCHRG LB, а остальное будет работать.

xaizek ★★★★★
()

Если я правильно помню, то upsc это же тулза из nut? А он может шатдаунить не только по состоянию батарей, но и тупо по таймауту.

MumiyTroll ★★★
()

А целиком NUT настроить не судьба? Он и выключать умеет, и ждать по времени и по напряжению на батарее, и случай восстановления электроснабжения во время шатдауна может разумно обработать, о чем не все знают.

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

Верно, с двойными скобками и костыль не нужен.

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

Примерно так.

У простых примеров всегда есть куча проблем. Например, ups уже почти полностью разрядился, потом на последней минуте питания появилось на 2 минуты и снова исчезло. Тогда всё грохнется через минут 5, а не 9. Потому надо не извращаться, а довериться нормальной мониторилки usp-ов и гаситься по минимуму батареи, а не тупому циклу.

А если stat может оказаться неопределен
[ «x$stat»

Вы натурально не знаете shell, как и ваши «подправлятели». Это защита не от пустого статуса, а от статуса с минусом впереди. От пустого статуса «$var» даст таки аргумент, пустой, но валидный.

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

У простых примеров всегда есть куча проблем.

Никто не спорит. Но автор спрашивает не «как это сделать правильно», а «как это сделать на баше».

Это защита не от пустого статуса, а от статуса с минусом впереди.

И правда. Когда вырабатывается привычка - забываешь, для чего, собственно, это делается.

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

Как здесь уже отметили, зачем городить очередной велосипед если есть стандартные работающие решения ?

Неужели ни NUT, ни apcupsd этот UPS не поддерживают ?

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

Спасибо за ответ

Выполнение изначальной версии скрипта выдаёт неверный синтаксис (перепроверила Sublime Text'ом, ошибки нет)

#!/bin/bash
count=0
while true
do
  stat=$(upsc ups@localhost ups.status)
  if [ "x$stat" = "xOB DISCHRG LB"]
  then
    count=$((count+1))
  else
    count=0
  fi
  [ $count -gt 9 ] && shutdown now
  sleep 60
done

1.sh: line 6: [: пропущен `]'

Версия с двумя квадратными скобками (6-ая строка - if [[ "x$stat" = "xOB DISCHRG LB"]] - выдает такой результат:

1.sh: line 6: syntax error in conditional expression
1.sh: line 7: ошибка синтаксиса около `then'
1.sh: line 7: `  then'

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

Спасибо за ответ!

Черновой вариант опробован успешно. Скрипт работает. Отключает комп через 30 секунд. Проверено пять раз. Т.е. команда отключения отправляется. И успешно выполняется. При удалении скрипта из крона, ИБП продолжает работать дольше, чем 30 сек. Как его докрутить?)

manik207
() автор топика
Ответ на: Спасибо за ответ от manik207

Пробел перед квадратной скобкой забыт. Баш, он такой. Вообще, рекомендую прислушаться к ораторам выше, тем более если с шеллом не особо.

Deleted
()
Ответ на: комментарий от alx777

nut поддерживает. Теме, где пытаюсь разобраться с ним nut'овскими настройками >20 дней. Буду рада помощи в ней.

manik207
() автор топика
Ответ на: Спасибо за ответ! от manik207

Отключает комп через 30 секунд.

Через 10 минут же должен (sleep 600). Или ты имеешь ввиду 30 секунд занимает выполнение команды «shutdown now»?

При удалении скрипта из крона

Его не по крону нужно выполнять, просто запустить один раз при запуске системы - цикл ведь бесконечный.

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

30 секунд - это если в крон добавить на ежеминутное выполнение.

Если просто его пустить и отрубить питание, сейчас именно команда shutdown now (для точности отключения - 2 секунды уходит на выполнение) приходит через 15 секунд.

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

Если просто его пустить и отрубить питание, сейчас именно команда shutdown now (для точности отключения - 2 секунды уходит на выполнение) приходит через 15 секунд.

Я там опечатался, написал !#/bin/bash, а правильно #!/bin/bash. Больше ошибок нет, должно работать как положено - отруб спустя 10 минут.

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

Перепроверила ещё раз с разными параметрами тайминговых значений. При любом сочетании значений (и 60/600, и 5/30 и много ещё каких) - сообщение мониторинга UPS о том, что команда выключения отправлена - появляется на 30й секунде.

Первая мысль, которую проверила - сама батарея вполне рабочая - без UPSного провода работает больше 10 минут (дольше не проверяла). Но машину тушит именно команда, и выглядит это как будто она не смотрит на все эти sleep's.

Что это может быть?

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

Аналогичная ситуация. Скрипт запускаю, жду. Через 30 секунд машина тушится скриптом. Включаю, меняю значения скрипта на другие sleep'ы - всё равно 30 секунд.

(Батарея живая из без внешних команд держится много минут).

Куда думать? На что смотреть?

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

Что это может быть?

Выглядит так, будто sleep сломан.

Попробуй выполнить в терминале sleep 60 && echo «Done». Посмотри, сколько секунд пройдет.

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

Возможно, тушится чем-то ещё.

Куда думать? На что смотреть

Заменить временно шатдаун на отладочный вывод. Запустить с отладкой bash -x. Собрать лог. Как-то так.
Судя по вашим вопросам, вы не совсем своим делом занимаетесь, это может оказаться долго и неконструктивно.

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