Так вчем проблема? Заходим по SSH и ребутим ... или я не понял вопроса...
инфа для размышления http://www.lghost.ru/lib/samag/conte...(38)-12-14.pdf
В этом треде оказались административно объединены две малосвязанные вещи --- нативная компиляция expect с выложенными бинарниками достаточно древних версий expect и tcl, и весьма любопытный скрипт от cyrax вынесенный в название темы. Читателям, которые интересуются собственно темой треда, рекомендую пропустить первые 11 постов и идти сразу сюда: expect на shell, или авто-телнеттинг
----------
Наблюдается многократно обсуждавшаяся проблема, что при разрыве соединения (предположительно со стороны провайдера), соединение не восстанавливается и в логе возникает (иногда многочасовая) вереница сообщений:
May 9 11:27:33 pppd[6319]: Timeout waiting for PADO packets
May 9 11:27:33 pppd[6319]: Unable to complete PPPoE Discovery
Олег рекомендовал выставить в дополнительных опциях pppd "maxfail 0", у меня в этой строке в веб-интерфейсе не стоит ничего, однако pppd запускается коммандой pppd file /tmp/ppp/options.wan0, и файл /tmp/ppp/options.wan0 содержит:
Т.е. эта опция включена по дефолтуPHP Code:
noauth refuse-eap
user xxx
password xxx
nomppe nomppc
plugin rp-pppoe.so rp_pppoe_service 'stream' nic-vlan1
mru 1492 mtu 1492
maxfail 0
usepeerdns
persist
ipcp-accept-remote ipcp-accept-local noipdefault
ktune
default-asyncmap nopcomp noaccomp
novj nobsdcomp nodeflate
lcp-echo-interval 10
lcp-echo-failure 6
unit 0
Проблема решается в 95% случаев путем перезагрузки ADSL модема.
Теперь собственно мой вопрос. Я могу сделать какую-нибудь сторожевую собаку, которая будет проверять лог на предмет этой ошибки и дальше хотелось бы удаленно перезагрузить модем. На модеме стоит тоже линукс, поддерживается логин через ssh и telnet. Как его перезагрузить...?
Один вариант мне видится таким --- создать специального юзера и сделать ему логин-шелл=/sbin/reboot , но честно говоря это означает модификацию прошивки модема, к чему я морально не готов...
В идеале хотелось бы что то вроде удаленного sh -c , но ничего подобного не могу найти
P.S. Провайдер --- стрим, ADSL модем Dlink DSL-500T, wl500gP (7g)
Last edited by al37919; 16-05-2011 at 14:31.
Так вчем проблема? Заходим по SSH и ребутим ... или я не понял вопроса...
инфа для размышления http://www.lghost.ru/lib/samag/conte...(38)-12-14.pdf
Last edited by Mirage-net; 09-05-2007 at 10:09.
Спасибо за сценарии на перле. Это как раз то что надо. Я и сам думал что то подобное сделать с помощью expect, но понадеялся может есть готовое решение попроще. Впрочем expect --- тоже гут , жалко нет в пакетах.
с этим не соглашусь в корне --- tcl прекрасно поддерживает regexp.но в нем немного не удобно с текстом работать (а ведь нужно лог обрабатывать)
В общем, в результате, таки откомпилил expect и сделал в нем (лежит у меня все таки душа больше к tcl нежели к perl ). expect отказался кросс-компилиться со следующей ошибкой (выдаваемой ./configure):
checking if WNOHANG requires _POSIX_SOURCE... configure: error: Expect can't be cross compiled
Эту ошибку я побороть не смог (если кто понимает как это обойти --- feedback is welcome). В результате сделал нативную компиляцию обоих последних версий (как expect-5.43, так и tcl-8.4.14 ) [tcl пришлось побить на две части, т.к. аттачмент ограничен 1 Мб]. Не ведаю как изготовить ipk путем нативной компиляции, так что прилагаю просто билды как первого, так и второго ( обращаю внимание, что они скомпилены для установки в /opt/local, а не в /opt , так что пути в /opt/local/bin , /opt/local/man , /opt/local/share/man должны быть прописаны куда следует)
В результате автоматическая перезагрузка ADSL модема у меня выглядит следующим образом (ежепятиминутно наличие соединения проверяется путем запуска из крона):
/opt/etc/cron.5mins/check_adsl.exp:
Code:#!/bin/sh # The following line is executed by /bin/sh and not by expect \ exec expect -f "$0" ${1+"$@"} proc check1 {} { spawn ping -c 10 www.stream.ru expect { -re {\d*\sbytes\sfrom\s[\d\.]*:\sicmp_seq=\d*\sttl=\d*\stime=[\d\.]*\sms} exit } check2 } proc check2 {} { spawn tail -n 3 /opt/var/log/syslog.log expect { "Timeout waiting for PADO packets" reboot_adsl "Unable to complete PPPoE Discovery" reboot_adsl } } proc reboot_adsl {} { spawn telnet 192.168.2.1 expect -exact "login: " send -- "admin\r" expect -exact "Password: " send -- "XXXXXXXX\r" expect -exact $::prompt_adsl send -- "reboot\r" set timeout 10 expect exec logger "$::argv0\[[pid]\]: Rebooting ADSL modem." puts "" } set timeout 60 set prompt_adsl "\r # " check1
А может как раз expect задействовать [это типа в виде обмена идеи на идею . Он как раз с курсами общаться могет: http://expect.nist.gov/FAQ.html#q22 ]
http://wl500g.info/showpost.php?p=55065&postcount=5
Last edited by al37919; 13-05-2007 at 21:33.
Я думаю, что можно перегрузить его и с помощью wget.
ЗЫ: у меня DSL-500G, без линуха, работает месяцами без проблем.
ЗЫЫ: А ещё, я не использую Service Name вообще.
wget??? Т.е. послать через wget ту инструкцию, которая выполняется при нажати кнопки save&reboot или как там она называется? Любопытно попробовать.
P.S. У этого случается заскок где то раз в неделю. Правда, обычно, когда что то подобное начинается, то повторяется несколько раз довольно часто, потом опять редко. Т.е., похоже, что-то происходит у провайдера. Вообще, для этого зверя тоже есть альтернативная прошивка, надо ее наконец будет попробовать.
Да, про wget всё правильно. Возможно прийдётся использовать нормальный wget из пакетов. Или curl.
Что касается СТРИМа, то если перегрузка модема помогает, то дело не в провайдере.
приклеить к кнопке включения палочку, положить рядом сдюк подключенный к компу, если надо перегрузить, выдвигаем удаленно сидюк, он своим выдвижным столом давит на палочку, та на кнопочку
При нажатии на 'Save and restart' вызывается:
/usr/www/html/tools/restartmodem.htm:PHP Code:
function SaveNBoot()
{
if(remote_user=="user")
{
alert("sorry, you're not authorised to modify this page.");
return false;
}
if(confirm("Save and restart?"))
{
document.getElementById("uiPostVarName").name = "logic:command/save";
document.getElementById("pagename").value = "../html/tools/restartmodem.htm";
document.getElementById("commandname").value="restart";
document.getElementById("uiPostrestart").value="1";
document.getElementById("pppdisconnect").disabled = false;
document.getElementById("uiPostForm1").submit();
}
}
т.е. вроде такая страница есть, но каким должен быть url, чтобы вызвать корректное действие... ?PHP Code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="../html/css/common.css" type="text/css">
<script language="JavaScript" src="../html/js/menu1.js"></script>
<script type='text/javascript'>
function callset()
{
if(document.getElementById("uiPostrestart").value == 1)
{
<? if eq $var:com restart `document.getElementById("uiPostVarName").name = "logic:command/reboot";`
'document.getElementById("uiPostVarName").name = "logic:command/defaults";' ?>
document.getElementById("uiPostrestart").value = 0;
document.getElementById("uiPostForm").submit();
}
// modify by Jarry for whether the lan IP change make sure the Reboot or Restore is correct 2005/02/19
//else
//{
<? if eq $var:com restart `setTimeout('document.location.href="http://<? query lan0:static:settings/ip ?>/cgi-bin/webcm?getpage=../html/index.html"', 45000);``<? if eq $var:ip restore `setTimeout('top.location.href="http://<? query lan0:static:settings/ip ?>/cgi-bin/webcm?getpage=../html/index.html"', 35000);`
`setTimeout('document.location.href="../html/index.html"', 35000);` ?>` ?>
//}
//setTimeout('document.location.href="http://192.168.1.1/cgi-bin/webcm?getpage=../html/index.html"', 42000);
}
</script>
</head>
<body topmargin=20 onload="callset()">
<script type='text/javascript'>
mainTableStart();
MapContent();
logo();
secondRow();
ThirdRowStart();
//Write_Item_Images();//left area
ThirdRowEnd();
inTableStart();
</script>
<table width=540px border=0 cellpadding=0 cellspacing=0 align=top height="500px">
<tr>
<td colspan=6 height="40" nowrap class="tabhead">Restarting...</td>
</tr>
<tr>
<td class="tabdata" height="50">The system is now restarting. Please wait.</td>
</tr>
<tr><td colsapn="6"></td></tr>
</table>
<script type='text/javascript'>
inTableEnd();
mainTableEnd();
</script>
<form method="POST" action="webcm" target="_self" id="uiPostForm" >
<!--
<input type="hidden" name="getpage" id="pagename" value="../html/tools/restartmodem.htm">
-->
<input type="hidden" name="getpage" id="pagename" value="../html/home/home_wizard.htm">
<input type="hidden" name="var:restart" value="<? echo $var:restart ?>" id="uiPostrestart">
<input type="hidden" id="uiPostVarName" name="" value="">
</form>
</body>
</html>
http://192.168.2.1/tools/restartmodem.htm показывает страницу:
и ничего не делает. Надо передавать параметры... А как их передать если метод POST?PHP Code:
Restarting...
The system is now restarting. Please wait.
Вроде с expect все как то проще получается
Привет,
да, давно не заходил сюда.
В общем хочу поделиться недавно написанным скриптом для тех, кому нужен expect (например для автоматической работы через телнет или вроде того).
Конечно есть пакет py_expect, но он на питоне и это не всегда удобно или возможно. Вот для таких случаев и будет полезен мой скрипт.
Для начала - пример, как это работает. В качестве примера - получение даты с другого устройства, например на DSL модеме.
Ну а теперь все остальное. Немного замудрено конечно с пайпами, но зато не надо в разных файлах ввод и вывод делать.Code:#!/bin/sh . /usr/local/sbin/mini-tools/expect.lib.sh # цепляем библиотеку (ее код дан ниже) expect_open -c telnet 192.168.10.1 # использование: expect_open [-c | -e <filename> ] <command> .... #опция -с включает дублирование вывода на консоль #опция -e включает дублирование вывода в <filename> #без опций - вывода нет expect login # ждем строку включающую в себя login - запрос имени пользователя send_line admin # отправляем строку с именем пользователя "admin" и перевод строки expect_eol # ждем перевод строки, который мы же и отправили ;) expect Password send_line password expect_eol expect_exact '#' # ждем строку состоящую только из # - запрос от shell'а expect_echo_start # для примера - включение вывода на консоль с этого момента send_line "date +%s;date +%m%d%H%M%Y.%S" expect_eol expect_capture_start # начало захвата вывода в переменную $EXPECT_OUTPUT, очищает переменную expect_eol # ждем перевода строки, т.е. в $EXPECT_OUTPUT будет вывод от первого date if [ $EXPECT_OUTPUT -le 86400000 ]; then echo 'Modem time is invalid' elif [ $EXPECT_OUTPUT -le `date +%s` ]; then echo 'Modem time is out-of-date' else expect_capture_start expect_eol #захватываем строку от второй команды date expect_capture_stop echo "Modem time is: $EXPECT_OUTPUT" # date -s $EXPECT_OUTPUT fi expect_close # закрываем запущенный процесс (телнет)
Из того, что точно криво сделано - это вхождение строки проверяю через вызов grep, т.к. ~= дает ошибку, а другого способа не знаю.
И еще не знаю как убрать CR когда он попадает в строку - это вызывает проблему с expect_exact если им ждать вывод с переводом строки.
Из того, что не доделано - таймаут. Мне он не оч нужен, но это не сложно, и если будут желающие, то постараюсь прикрутить.
expect.lib.sh
Надеюсь будет полезно кому-нить.Code:#!/bin/sh local EXPECT_APP_PIPE_IN local EXPECT_APP_PIPE_OUT local EXPECT_APP_ECHO local EXPECT_INJECT_LINE local EXPECT_OUTPUT local EXPECT_CAPTURE=false local EXPECT_APP_ID expect_open () { # $1=echo_file $2+=app case "$1" in '-e') shift; expect_echo_start "$1"; shift;; '-c') shift; expect_echo_start;; *) expect_echo_stop; esac local RUN="$@" set `dd if=/dev/urandom bs=1 count=4 2>/dev/null|od -D` RND=${2##0000000 } RND=${RND%% 0000004} readonly EXPECT_APP_PIPE_IN=/tmp/tmp.$$.$RND.pipe-in mkfifo $EXPECT_APP_PIPE_IN readonly EXPECT_APP_PIPE_OUT=/tmp/tmp.$$.$RND.pipe-out mkfifo $EXPECT_APP_PIPE_OUT readonly EXPECT_INJECT_LINE="-INJECT-$$-$RND-" $RUN <$EXPECT_APP_PIPE_IN >$EXPECT_APP_PIPE_OUT & EXPECT_APP_ID=$! exec 8>$EXPECT_APP_PIPE_IN #/proc/$EXPECT_APP_ID/fd/1 exec 9<$EXPECT_APP_PIPE_OUT usleep 100000 #need to get the spawned app running as it is in background } expect_handle_input () { #$1 - handler #$2+ - handler params local BUFFER local LINE local N_LINE local RET_RES local HANDLER=$1 shift local PARAMS="$@" local HAD_DATA_LINE=false export HAD_DATA_LINE local STOP_LINE=false export STOP_LINE while true; do echo $EXPECT_INJECT_LINE >$EXPECT_APP_PIPE_OUT while read N_LINE <&9; do STOP_LINE=false LINE="${N_LINE%$EXPECT_INJECT_LINE}" if [ "$N_LINE" == "$LINE" ]; then HAD_DATA_LINE=true LINE="$BUFFER${LINE%%' '}" BUFFER="" echo "$LINE" >$EXPECT_APP_ECHO if $EXPECT_CAPTURE; then EXPECT_OUTPUT="$EXPECT_OUTPUT$LINE"; fi # FULL-LINE $HANDLER 0 "$LINE" "$@" elif [ "$LINE" ]; then BUFFER="$BUFFER$LINE" LINE="${BUFFER}" # PART-LINE $HANDLER 1 "$LINE" "$@" else STOP_LINE=true # HAD_DATA_LINE? PART-LINE $HANDLER 2 "$LINE" "$@" fi RET_RES=$?; if [ $RET_RES -ne 1 ]; then if [ "$BUFFER" ]; then echo -n "$LINE" >$EXPECT_APP_ECHO if $EXPECT_CAPTURE; then EXPECT_OUTPUT="$EXPECT_OUTPUT$LINE"; fi fi return $RET_RES elif $STOP_LINE || [ "$BUFFER" ]; then break fi done if [ ! -d /proc/$EXPECT_APP_ID ]; then break fi usleep 50000 done echo "$BUFFER" >$EXPECT_APP_ECHO if $EXPECT_CAPTURE; then EXPECT_OUTPUT="$EXPECT_OUTPUT$LINE"; fi return 2 } __input_handler_match_any () { if $STOP_LINE && $HAD_DATA_LINE; then return 0 fi return 1 } __input_handler_match_all () { return 1 } __input_handler_match_eol () { if [ $1 == 0 ]; then return 0 fi return 1 } __input_handler_grep () { if echo "$2" | grep "$3" > /dev/null ; then return 0 fi return 1 } __input_handler_match () { local T="${2%% }" if [ "${T## }" == "$3" ]; then return 0 fi return 1 } expect_any_line () { expect_handle_input __input_handler_match_any } expect () { expect_handle_input __input_handler_grep "$1" } expect_exact () { expect_handle_input __input_handler_match "$1" } expect_eol () { expect_handle_input __input_handler_match_eol } send () { echo -n "$@" >&8 } send_line () { echo "$@" >&8 } expect_capture_start () { EXPECT_OUTPUT='' EXPECT_CAPTURE=true } expect_capture_continue () { EXPECT_CAPTURE=true } expect_capture_stop () { EXPECT_CAPTURE=false } expect_echo_start () { if [ "$1" ]; then EXPECT_APP_ECHO="$1" else EXPECT_APP_ECHO=/proc/$$/fd/1 fi } expect_echo_stop() { EXPECT_APP_ECHO='/dev/null' } expect_close_now() { exec 8>&- exec 9<&- rm $EXPECT_APP_PIPE_IN rm $EXPECT_APP_PIPE_OUT } expect_close() { exec 8>&- if [ "$EXPECT_APP_ECHO" != '/dev/null' ]; then expect_handle_input __input_handler_match_all fi exec 9<&- rm $EXPECT_APP_PIPE_IN rm $EXPECT_APP_PIPE_OUT } expect_clean_up() { exec 8>&- exec 9<&- rm /tmp/tmp.$$.*.pipe-in rm /tmp/tmp.$$.*.pipe-out }
Если что - пишите, но быстрой реакции не обещаю.
Я гашу "детский" комп через ssh. sshd на винде организовать не так уж сложно. Есть пакет copSSH. Это openssh из cygwin оформленный в виде виндового инсталятора. При установке могут быть проблеммы с именем группы Администраторы, тогда надо переименовать на латиницу. Сейчас не помню где было такое, под XP, w2k3 или вистой.
Я юзаю openssh и другие полезные линуксовые утилиты устанавливая cygwin. В этом случае для запуска sshd доки нужно читать .
Спасибо большое за идею! Я тут http://www.itefix.no/phpws/index.php...age&PAGE_id=12
нашел прогу для винды openssh
Установил, Настроил, РАБОТАЕТ! Теперь гашу "детский" комп "вручную" c Putty-
ssh username@192.158.1.51
ввожу password
shutdown -s
Хочу это автоматизировать, чтобы запускать кроном...
и теперь Сделал скрипт-remotepcshutdown.sh
Но не заработало- выдает-Code:#!/bin/sh spawn ssh username@192.158.1.51 expect "Password:" send "password\r" send "shutdown -s"
А как исправить?Code:./remotepcshutdown.sh: ./remotepcshutdown.sh: 2: spawn: not found ./remotepcshutdown.sh: ./remotepcshutdown.sh: 3: expect: not found ./remotepcshutdown.sh: ./remotepcshutdown.sh: 4: send: not found ./remotepcshutdown.sh: ./remotepcshutdown.sh: 5: send: not found
Спасибо!