Что нового

Автоматическое закрытие PUTTY при завершении работы

Numbot

In God We Trust
Сообщения
9
Репутация
0
Добрый день!
Прошу прощения за беспокойство - я новичок и очень нуждаюсь в указующем персте или пинке, что бы дойти до решения.
Уже несколько дней курю форум, но решение на свою задачу так пока и не нашел\придумал.
Помогите пожалуйста или направьте туда где есть аналогичные примеры.
Дело в следующем:
Есть вот такой вот простенький скрипт :
Код:
Run("C:\Program Files (x86)\PuTTY\putty.exe")			;запуск "путти"
WinWait("PuTTY Configuration","Cate&gory:")			;ожидание активности окна

   Sleep (2000)								

ControlSend("PuTTY Configuration","Cate&gory:","Edit1",'адрес сервера')	;передача в окно "путти" адреса к которому необходимо подцепиться
ControlSend("PuTTY Configuration","Cate&gory:","Edit1","{Enter}")

   Sleep (2000)

Send ('логин')							;логин на сервер
Send ("{Enter}")

   Sleep (1000)

Send ('пароль')							;пароль на сервер
Send ("{Enter}")

   Sleep (2000)
   
Send ('cd ..')							;выход в home dir
Send ("{Enter}")

Send ('cd ..')
Send ("{Enter}")

Send ('cd /путь к скрипту')					;путь к исполняемому скрипту
Send ("{Enter}")

   Sleep (1000)

Send ('./скрипт.sh')						;запуск исполняемого скрипта
Send ("{Enter}")


- Скрипт запускается по расписанию в нужное время запускает клиент PUTTY,
- Вводит в окно PUTTY адрес сервера,
- Подключается к серверу,
- Передает логин и пароль для авторизации,
- Переходит в нужную директорию
- Запускает на исполнение скрипт, который может работать 2-3 а то и 6 часов.
- Окно PUTTY все это время должно быть открыто
- Результатом работы скрипта будет заведомо известная строчка в окне PUTTY ("Output successfuly done")
Вопрос:
Как сделать так, что бы после появления этой надписи, окно PUTTY автоматически закрылось?
Заранее спасибо.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
А если так:
Код:
$iPID = Run("C:\Program Files (x86)\PuTTY\putty.exe")
;
; Тут код скрипта
;
While 1
	Sleep(500)
	If WinExists("PuTTY Configuration", "Output successfuly done") Then 
		ProcessClose($iPID)
		Exit		; Если требуется завершение работы скрипта
	EndIf
WEnd
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
К сожалению не работает =(
Судя по всему, autoit не видит окончания работы дочернего скрипта (текста ""Output successfuly done" в окне PuTTY"), потому что скрипт заканчивает работу, но скрипт все время висит в режиме ожидания.
Попробовал указать на окно через класс, но то ли я что то не так понимаю, то ли оно так не работает как я понимаю =(

Код:
$iPID = Run("C:\Program Files (x86)\PuTTY\putty.exe")			;старт скрипта
WinWait('[CLASS:PuTTY]', '', 5)						;ожидание окна

;
;тело скрипта
;
;./start.sh

While 1
    Sleep(500)
	    If WinExists("[CLASS:PuTTY]", "Output successfuly done") Then
        ProcessClose($iPID)
        Exit        ; Если требуется завершение работы скрипта
    EndIf
WEnd
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
А скрин Windows Info с этим текстом можете сделать?
Есть это текст в Visible Text?
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
К сожалению в Windows info на вкладке Visible Text нет никакой информации :'(
Ниже:
- скрин окна PuTTY
- скрин Windows info "Visible Text"
- скрин Windows info "Summary"
 

Вложения

edyapd

Осваивающий
Сообщения
380
Репутация
30
Если скрипт не видит текста в окне, то даже не знаю, как к нему можно привязаться.
Может ещё кто-нибудь, что-нибудь посоветует.
 

---Zak---

Скриптер
Сообщения
438
Репутация
113
Numbot
В настройках PuTTy имеется "Session Log". Попробуйте через него.

Суть:
Запускаем AutoIT и чистим файл с "Session Log" / или переименовываем старый.
Запускаем PuTTy + ... + запускаем исполняемый скрипт.
После делаем цикл на поиск фразы в файле: "Output successfuly done".
Если такая имеется - ProcessClose
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
А вот это может сработать! :think:
Проверил - PuTTY может писать\дополнять или переписывать лог на каждой сессии.
Проблему вижу только если нужно запустить одновременно два PuTTY (если допустим есть необходимость запустить скрипт дважды или два скрипта)
Но тут уже можно рулить и поставить два разных клиента PuTTY, обозвать логи разными именами, что после отобразить в коде...
Простая задача становится все интереснее и интереснее... :think:
Спасибо за идею - я попробую и обязательно отпишусь!
:beer:
 

darkwhite

Новичок
Сообщения
129
Репутация
4
в комлекте с Putty есть утилита для работы в командной строке plink, а вот уж с ним работать можно посредством работы с консолью (через run) например вот так
Код:
$pidplink = Run("plink "&$local_ip&" "&$gate_user&"@"&$gate_name&" -pw "&$gate_pass&" -P "&$gate_port, @ScriptDir, @SW_SHOW, $STDOUT_CHILD + $STDERR_CHILD+$STDIN_CHILD)

$Form=GUICreate("Подключение к Серверу v0.3",210,60,@DesktopWidth/2-105,@DesktopHeight/2-15,$WS_CAPTION)
$Message=GUICtrlCreateLabel("Подлючаюсь к серверу "&@CRLF&$gate_name&"...",10,10,200,30)
GUISetState()
$BeginConnect=TimerInit()
while 1
    $cons_string = StdoutRead($pidplink)
;~     $a = @extended
;~     $ind = @error
    Sleep(100)
;~     If $a <> 0 Then
;~         MsgBox(0, '', 'Bytes = ' & $a)
;~         MsgBox(0, "STDOUT read:", _WinAPI_OemToChar($cons_string))
;~ 		_FileWriteLog('logrdp.txt',_WinAPI_OemToChar($cons_string))
;~ 	EndIf
	if StringRegExp(_WinAPI_OemToChar($cons_string),'(?i)(Welcome.*)',0) then ExitLoop ; искомая строка 
	if TimerDiff($BeginConnect)/1000 > 300 then
		MsgBox(0,"Ошибка соединения с "&$gate_name, "Во время соединения с сервером "&$gate_name&" произошла ошибка. Либо отсуствует подключение к Интернет, либо сервер "&$gate_name&" выключен")
		ProcessClose($pidplink)
		Exit
	EndIf
	if ProcessExists($pidplink)=0 then exit
WEnd
GUICtrlSetData($Message,"Соединение с сервером "&@CRLF&$gate_name&" установлено!")

StdinWrite($pidplink,"exit"&@CR)
	$cons_string = StdoutRead($pid)
;~ 	$a = @extended
;~     $ind = @error
    Sleep(3000)
;~     If $a <> 0 Then
;~         MsgBox(0, '', 'Bytes = ' & $a)
;~         MsgBox(0, "STDOUT read:", _WinAPI_OemToChar($cons_string))
;~ 		_FileWriteLog('logrdp.txt',_WinAPI_OemToChar($cons_string))
;~ 	EndIf
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
[Окна, Диалоги] Re: Автоматическое закрытие PUTTY при завершении работы

Всем привет!
Спустя почти 3 недели изучения autoit с нуля вернулся и хочу поблагодарить откликнувшихся и поделиться наработками. :IL_AutoIt_1:
Может быть будут полезны кому-нибудь.
Отдельное спасибо товарищу "darkwhite", но твой код довольно сложный и для меня пока "не в ногу"....пока =)
Ниже описание сотворенного с комментариями + вопрос

Код:
#include <WinAPIEx.au3>

$pid1 = Run("C:\temp1\kitty1\kitty.exe") ;разделение процессов было применено т.к. необходим запуск нескольких окон одновременно + пришлось перейти с Putty на Kitty поскольку Kitty позволяет хранить настройки конфигурации рядом с исполняемым файлом, что позволяет открыть несколько окон с разными конфигурациями (касательно логирования)
Sleep(300)
$win1 = _WinAPI_EnumProcessWindows($pid1)
WinWaitActive('[CLASS:KiTTY]', '', 5)

ControlSend("KiTTY Configuration","Cate&gory:","Edit1",'адрес_сервера')
ControlSend("KiTTY Configuration","Cate&gory:","Edit1","{Enter}")

WinActivate($win1[1][0])
Sleep (2000)
ControlSend("имя_окна- KiTTY","","",'логин')
ControlSend("имя_окна- KiTTY","","","{Enter}")

WinActivate($win1[1][0])
Sleep (1000)
ControlSend("имя_окна- KiTTY","","",'пароль')
ControlSend("имя_окна- KiTTY","","","{Enter}")

WinActivate($win1[1][0])
Sleep (700)
Send('cd ..') ; далее отправляется путь на сервере к скрипту, который будет запускаться скриптом  :stars:
Send("{Enter}")

WinActivate($win1[1][0])
Sleep (700)
Send('cd ..')
Send("{Enter}")

WinActivate($win1[1][0])
Sleep (700)
Send('cd _путь на сервере к исполняемому скрипту')
Send("{Enter}")

WinActivate($win1[1][0])
Sleep (700)
Send('./запуск скрипта.sh') ; собственно запуск скрипта
Send("{Enter}")

$hFile = FileOpen("C:\temp1\kitty1\putty1.log") ; в Kitty включена настройка логирования действий. Тут мы откр. файл для чтения

; далее цикл построчного чтения файла в поисках заданной строки с последующим выходом из цикла при нахождении

While 1
   Sleep(100)
   $sLine = FileReadLine($hFile) ;читаем построчно наш файл
   If StringInStr($sLine, 'ТО_ЧТО_НАДО_НАЙТИТЬ...') Then ExitLoop
   WEnd

WinActivate($win1[1][0])
Sleep(1000)
ControlSend("имя_окна","","",'exit')
ControlSend("имя_окна","","","{Enter}")
 Exit

; изначально изобрел велосипед и убивал процесс следующим образом, но потом поспал и придемал вариант выше - он как то попроще и логичнее =)

 ;Sleep (1000)
;WinClose ('ИМЯ_ОКНА') ; эмуляция нажатия на крестик (закрытие процесса) =)
;Sleep (700)
;ControlSend("KiTTY Exit Confirmation","","","{ENTER}") ; отправка етрера к подтверждающему окну


Вопрос в следующем:
Скрипт запущен и работает, но есть подозрение, что работает он очень медленно, а так же тормозит работу скриптов на сервере.
Подозрения падают на эту функцию:
Код:
While 1
   Sleep(100)
   $sLine = FileReadLine($hFile) ;читаем построчно наш файл
   If StringInStr($sLine, 'ТО_ЧТО_НАДО_НАЙТИТЬ...') Then ExitLoop
   WEnd


Дело в том, что данные логи довольно объемные (порядка 1-2 mb)
Возможно при каждом их изменении, скрипту необходимо прочитать из заново?
Возможно ли как-то улучшить данный алгоритм поиска?
Или изменить его в качественно лучшую сторону?
Заранее всем спасибо!
:beer:
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
А зачем вам в этом цикле нужна команда Sleep(100)? Если файл около 1МБ, то при длине строки в 100 байт, только на эту команду уйдёт примерно 18 минут, при поиске до конца файла.
И почему надо читать именно по одной строке? Не проще прочитать всё сразу, а потом обрабатывать в памяти?
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
Вооот....я так и знал! :-[
Вот тут могу повторить начало последнего сообщения (2) или процитировать самое начало (1):
1 - "Прошу прощения за беспокойство - я новичок и очень нуждаюсь в указующем персте или пинке, что бы дойти до решения"
2 - "Спустя почти 3 недели изучения autoit с нуля"
Так же, мои познания в программировании, в общем смысле этого слова, ограничены курсами средней школы лет 10 назад, когда бейсик был очень крут, а знающих паскаль среди знакомых было <>0 но <1.
В общем буду признателен за подсказку "как" или ссылку "где"...
Спасибо заранее!
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
Всем привет.
Я ну очень настойчивый, когда сильно нужно :whistle:
Друзья, ещё раз нужна ваша консультация и помощь:
Начало задачи можно почитать выше
Кратко:
- Есть скомпилированный скрипт, который в заданное время запускается XStart_ом и посредством PUTTY (KiTTY) коннектится к удаленному серверу, где запускает ещё один скрипт.
- В KiTTY включено логирование сеанса и все действия второго скрипта пишутся в лог
- Задача после того как в логе появится заранее известная строчка (на это может уйти 4-8 часов) закрыть соединение с сервером.
Выше можно посмотреть предыдущую реализацию - есть подозрение, что алгоритм поиска там не оптимален (большое спасибо "edyapd" за подталкивание к нужной мысли :beer: )
Ниже мной был найден кусочек кода, который, я чувствую, могу прикрутить к своему коду, но я не очень понимаю, как он работает в деталях и как его прикрутить.
Вопроса 2:
- Поясните пожалуйста что в приведенном коде обозначают строчки с вопросами в комментариях?
- Как сделать так что бы данный кусочек запускался в цикле скажем каждые полчаса и проверял наличие нужной строчки в файле?
Заранее спасибо за ответ.

Код:
#include <Array.au3>

$sTemp = ''											; переменная
$sTest = 'test'										; то, что будем искать
$i = 0												; обнуление переменных???
$j = 0												; Обнуление переменных???
Dim $aTest[1]										; Dim используется для объявления уже существующих переменных???
$hFile = FileOpen('C:\BlahBlahBlah\putty.log', 0) 	; открываем файл для чтения
   While 1								;вход в цикл
    $i += 1								;???
    $sTemp = FileReadLine($hFile, $i) 	; считывает строку из файла (в параметрах путь к файлу + номер строки с которой начинается считывание)
    If @error = -1 Then ExitLoop		; ???
    If StringInStr($sTemp, $sTest) Then ; ???
        $j += 1                         ; ???
        ReDim $aTest[$j + 1]            ; ???
        $aTest[$j] = $i                 ; ???
    EndIf								; выход из IF
   WEnd									; выход из цикла
FileClose($hFile)						; закрываем файл
If Not $j Then							; ???
    MsgBox(0, '', 'Нет совпадений.')    ; выводим сообщение
   Else									; иначе
    WinClose ("[CLASS:Notepad]", "")	; закрываем процесс блокнота
 EndIf									;
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Numbot сказал(а):
- Как сделать так что бы данный кусочек запускался в цикле скажем каждые полчаса и проверял наличие нужной строчки в файле?
Код:
AdlibRegister('ReadLog', 30*60*1000)
Global $sTest = 'test'

While 1
	Sleep(500)
WEnd
 
Func ReadLog()
	$hFile = FileOpen('putty.log', 0)
	$sTemp = FileRead($hFile)
    If StringInStr($sTemp, $sTest) Then 
		ConsoleWrite("Совпадение найдено" &@LF)
	Else
		ConsoleWrite('Нет совпадений.' & @LF)
	EndIf
	FileClose($hFile)
EndFunc
По хорошему надо бы вставить ещё проверку на наличие файла putty.log
 
АТ
Numbot

Numbot

In God We Trust
Сообщения
9
Репутация
0
Всем спасибо - тема закрыта!
Отдельное товарищу "edyapd" - плюсанул :beer:
Реализация получилась на мой взгляд самодостаточная, уникальная и элегантная :-[
Тестирование завершено успешно - все работает как и задумывалось.
Далее уже есть хотелки по поводу отправки сообщений по SMTP при окончании работы, но это уже другая тема.
Всем спасибо.
Под спойлером полный листинг программы (может кому нибудь пригодится).
:IL_AutoIt_1:

Код:
#include <WinAPIEx.au3>

$pid1 = Run("C:\temp1\kitty1\kitty.exe")
Sleep(300)
$win1 = _WinAPI_EnumProcessWindows($pid1)

ControlSend("KiTTY Configuration","Cate&gory:","Edit1",'адрес_сервера')
ControlSend("KiTTY Configuration","Cate&gory:","Edit1","{Enter}")

Sleep (2000)
ControlSend("имя_окна- KiTTY","","",'имя_пользоваталя')
ControlSend("имя_окна- KiTTY","","","{Enter}")

Sleep (1000)
ControlSend("имя_окна- KiTTY","","",'пароль')
ControlSend("имя_окна- KiTTY","","","{Enter}")

Sleep (700)
Send('cd ..')
Send("{Enter}")

Sleep (700)
Send('cd ..')
Send("{Enter}")

Sleep (700)
Send('полный_путь_с_скрипту_на_сервере')
Send("{Enter}")

Sleep (700)
Send('./имя_скрипта.sh')
Send("{Enter}")

AdlibRegister('ReadLog', 15*60*1000) ; каждые 15 минут
Global $sTest = 'то_что_надо_найти_в_файле'

While 1
    Sleep(500)
WEnd

Func ReadLog()
    $hFile = FileOpen('C:\temp1\kitty1\putty1.log', 0) ; читаем файл в переменную
    $sTemp = FileRead($hFile)
   If StringInStr($sTemp, $sTest) Then
   ProcessClose ($pid1)
Exit
   Else
	  EndIf
   FileClose($hFile)
 EndFunc
Exit
 
Верх