Чтиво: офис и дом, часть 003
SIM в "Online" или о пользе удаленного управления софтом.
Опять же счастливых обладателей выделенок данная заметка не коснется,
хотя, наверное, из нее они смогут что-то для себя почерпнуть.
Для общения помимо электронной почты, я использую ICQ (I seek you), а
конкретно клиента SIM (Simple Instant Messenger), не буду писать почему
я пользуюсь именно им, просто он мне понравился. В ходе его
использования выявился обычный для таких программ досадный недочет:
когда теряется связь с сервером ICQ, т.е. произошло dialup-разъединение,
клиент честно переходит через некоторое время в режим "Offline", а
поднять его из этого режима обратно в "Online" можно только ручками, что
не очень удобно, ибо все время забываешь это сделать, когда кто-то из
локальной сети (да даже и сам) выходит в Интернет. В клиенте Trillian
под Windows это решалось просто - там есть возможность поставить
временной промежуток, после прошествия которого Trillian вновь
опрашивает сервер на предмет его доступности и переводит себя в
"Online". В SIM я такой возможности не нашел (может плохо искал, тогда
ткните меня в нее). Это меня по началу расстроило. Но как-то раз при
просмотре списка файлов поставляемых в дистрибутиве SIM
$ rpm -ql sim | less
я обнаружил программку simctrl, назначение которой я не понял - в "man
simctrl" и "simctrl --help" было пусто. Тогда я решил искать описание ее
в другом месте. Для начала
$ cat /usr/share/doc/sim-0.9.2/README | less
Там информации на эту тему не оказалось, зато была ссылка на сайт
http://sim.shutoff.spb.ru/ - он в русской зоне и я понадеялся что там
будет вразумительная информация на русском языке. Сходу никакой полезной
для меня информации не обнаружилось, поэтому я начал бродить по
описаниям плагинов SIMа. И, о, чудо! ;) В описании плагина "remote" я
увидел:
Удаленное управление
Модуль удаленного управления позволяет управлять SIM из других программ
или с другого компьютера.
Вид связи устанавливается в настройках модуля.
Возможные варианты:
- UNIX-сокет (для *nix) используется по умолчанию
- TCP-сокет
- OLE automation (для win32) используется по умолчанию
При использовании TCP-соединения можно воспользоваться telnet.
В других случаях используется программа simctrl. Вызов команды simctrl:
simctrl [-s socket] [-c command]
socket - имя сокета для управления (если не указано, то используется
сокет по умолчанию) command - команда которую надо выполнять. Если
команда не указана, то используется поток команд из стандартного ввода,
результаты выполнения команд выводятся на стандартный вывод.
Получить список команд и их параметры можно с помощью команды HELP.
С помощью эти интерфейсов производится обработка файлов .uin (файлов
ICQ) для добавления в контакт-лист и отправки сообщения, а также
интеграция с explorer в win32 (расширение контекстного меню по правой
кнопки для файлов для отправки их через SIM)
Что ж, это то что мне требовалось знать о данной программе. Итак,
начнем:
Двойной щелчок по иконке SIM -> появляется Main Window, в нем кликаем по
кнопке Menu (в виде треугольничка вниз в верхнем правом углу) -> Setup
-> Plugins - Remote Control -> устанавливаем галочки в "Plugin enabled",
затем, "Use TCP socket" - Port: "16008" - > "Apply". Все.
Почему TCP-сокет? А фиг знает. UNIX-соекты у меня не захотели работать.
Порт можно любой, но я под влиянием программы linesrv, которая сидит на
16007, сделал 16008 ;)
Сейчас попробуем по управлять:
$ telnet 127.0.0.1 16008
>HELP
Выводит список доступных команд, среди них есть "STATUS"
>STATUS
STATUS Offline
Она выводит и устанавливает текущий режим SIM. Нескольких экспериментов
я выяснил, что для того, чтобы SIM был в сети нужно сказать:
>STATUS Online
Чтобы отключился:
>STATUS Offline
Выход из удаленного управления:
>CLOSE
Не путать с QUIT, который завершает работу SIM.
Здорово! Это меня натолкнуло на мысль написать скрипт, который бы
проверял наличие соединения с Интернет, и в зависимости от этого
переводил бы SIM в "Online" или "Offline". Опять же я провел несколько
пробных испытаний, почитал доков и понял, что писать скрипт для меня
удобнее в Perl, тем более я его плохо знаю, а это минус - написанием
скрипта немного поднимем свою квалификацию. После продолжительных боев с
telnet, sim, nedit, perl, man и opera (в которой я читаю всякие доки) у
меня получилось следующее:
begin ~/bin/sim.sh #!/usr/bin/perl
use IO::Socket;
use Net::Ping;
use Sys::Syslog qw(:DEFAULT setlogsock);
# Имя программы
$simspy = "sim.sh";
# Адрес и порт по которому происходит соединение с
# плугином SIM Remote Control
$host = "127.0.0.1";
$port = 16008;
# Величина задержки между опросами сети
$delay = 30;
# Процедура записи сообщения через syslog
sub mess2syslog {
setlogsock("unix");
openlog ("sim-spy", "nowait|pid", "user");
syslog ("local5|err", $_[0]);
closelog ();
}
# Предотвратить повторный запуск sim-spy
if (!system("ps -u".$<." -o \'pid uid command\' | grep ".$simspy." | grep -v
".$$." | grep -v grep > /dev/null")) {
mess2syslog("SIM-spy already run");
exit;
}
# Перевод программы в режим демона
if (!defined($child_pid = fork())) {
die "cannot fork: $!";
} elsif ($child_pid) { exit;}
else { # I'm the child
}
mess2syslog("SIM-spy started");
$p = Net::Ping->new();
while ( 1 == 1 ) {
# Проверка на запущенный SIM, если нет - запускаем
if ($status = system("ps -ax | grep sim | grep -v grep | grep -v ".$simspy."
> /dev/null")) {
unless (fork()) {exec("sim")}
mess2syslog("SIM not run. Running...");
wait();
}
# Существует возможность соединения с сервером ICQ?
if ($p->ping("205.188.179.233",5)) {
# Осуществление соединения с SIM Remote Control
$socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto
=> "tcp", Type => SOCK_STREAM);
if (defined $socket) {
# Проверка текущего статуса SIM
$socket->print ("STATUS\n");
CExitOn:
while (<$socket>) {
# Если статус Offline, то произвести переключение в Online
if ( $_ =~ /Offline/ ) {
$socket->print ("STATUS Online\n");
mess2syslog("Connection with ICQ established. Change SIM-status to
Online");
last CExitOn;
} elsif ( $_ =~ /Online/ ) {
last CExitOn;
}
}
} else {
mess2syslog("Connection with ICQ established. Can't open SIM-socket");
}
close ($socket);
} else {
# Осуществление соединения с SIM Remote Control
$socket = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto
=> "tcp", Type => SOCK_STREAM);
if (defined $socket) {
# Проверка текущего статуса SIM
$socket->print ("STATUS\n");
CExitOff:
while (<$socket>) {
# Если статус Online, то произвести переключение в Offline
if ( $_ =~ /Online/ ) {
$socket->print ("STATUS Offline\n");
mess2syslog("Connection with ICQ lost. Change SIM-status to Offline");
last CExitOff;
} elsif ( $_ =~ /Offline/ ) {
last CExitOff;
}
}
} else {
mess2syslog("Connection with ICQ lost. Can't open SIM-socket");
}
close ($socket);
}
# Задержка
sleep ($delay);
}
$p->close();
end ~/bin/sim.sh Что происходит благодаря этому скрипту? При запуске скрипт переходит в
фоновое выполнение, следит за наличием программы sim, если ее нет в
списках процессов (не запущена изначально или "рухнула" в результате
ошибки), то запускает ее, затем, он проверяет наличие соединения с
сервером ICQ - если оно есть, то через TCP-сокет говорит SIM перейти в
"Online", а если соединения нет, то в "Offline". После чего вся
процедура повторяется через 30 секунд. Предусмотрено журналирование
работы программы через syslog. Замечательно!
Можно удостовериться в работе программы:
$ sim.sh
"Убиваем" SIM (можно, конечно и через обычный "Quit" в программе ;):
$ kill `ps -u koal | grep -e 'sim$' | grep -v grep | awk '{print $1}'`
Через некоторое время SIM появляется вновь (серая ромашка). Также
пробуем войти-выйти из Интернет c паузой в этих действиях. У меня это
делается через GUI клиента сервера linesrv. SIM должен сначала перейти в
"Online" (зеленая ромашка), затем обратно в "Offline" (красная ромашка).
Осталось занести sim.sh в автозапуск:
"Пуск" (кнопка в левом нижнем углу рабочего пространства для GNOME) ->
"Параметры" -> "Сеансы" -> вкладка "Автоматически запускаемые программы"
-> кнопка "Добавить" -> "Команда запуска" - "/home/koal/bin/sim.sh",
"Порядок" - "90" (чем меньше порядок, тем первее запускается программа -
в нашем случае лучше чтоб позднее) -> "OK" -> "Закрыть"
Теперь "sim-spy" будет запускаться автоматически, после того как я
наберу login и password.