unix 2015-07-25 16-36-43
Jabber Shell Bot — теперь поддерживает русский
Есть много видов удаленного администрирования. Многие предпочитают граффику (vnc, rdp), многие старую добрую тру-консоль (sshd, telnetd). Но а если все эти навороченные сервера удаленного управления упали? Ничего не работает, никак не поднять, а файлы получить срочно нужно. Тогда спасает jabber shell bot. Казалось бы что за ненужная вещь по сравнению с теме ssh? Да вот только именно через него бородатые сисадмины зачастую и перезапускают ssh.
Теперь к делу:
jabber shell bot требует устанновленного perl’а.
Устанавливаем perl:
pacman -Sy perl
Скрипт требует библиотеки Net::XMPP, Net::Jabber, utf8 и Encode. Устанавливаем их через cpan:
cpan
install Net::XMPP
install Net::Jabber
install utf8
install Encode
Вот сам скрипт: http://dpaste.org/E9np/
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Net::XMPP;
use Net::Jabber;
use utf8;
use Encode;
# Список файлов конфигурации для перебора
my @configs = (
$ENV{'HOME'}.'/.jabber-shell', # Пользовательский файл конфигурации
'/etc/jabber-shell.conf', # Системный конфиг
);
# Хэш для хранения настроек
my %settings;
# Перебираем все файлы конфигурации
foreach my $config (@configs) {
# Если файл существует и доступен для чтения
if ( ( -e $config ) && ( -r $config) ) {
# Читаем конфигурацию
open(CONFIG, '<'.$config);
local $/ = undef;
my $config_data = <CONFIG>;
close(CONFIG);
%settings = eval($config_data);
# Выходим из цикла
last;
}
}
# Если не удалось прочитать настройки - завершаем работу
if (!%settings) {
die("Can't read settings!");
}
# Массив, в котором будут JID админов
my @admins = split(' ', $settings{'admins'});
# Определяем основные перменные
my $client = new Net::Jabber::Client();
my $presense = Net::Jabber::Presence->new();
# Определяем обработчики событий
$client->SetCallBacks(
'message' => \&on_message,
);
# Подключаемся к сети
# TODO: Обрабатывать ошибки подключения
$client->Connect(
'hostname' => $settings{'server'},
'port' => $settings{'port'},
);
my @connect = $client->AuthSend(
'username' => $settings{'username'},
'password' => $settings{'password'},
'resource' => $settings{'resource'},
);
# Устанавливаем статус
$presense->SetType("available");
$presense->SetStatus("");
$client->Send($presense);
# Функция обработки команд
sub process_command {
my $command = shift;
my $message = '';
# Если команда cd - пытаемся сменить директорию
if ($command =~ s/^cd([ ]+)//) {
if (chdir($command)) {
$message = 'Directory changed';
}
else {
$message = 'Directory NOT changed';
}
}
# Если какая-то другая - выполняем её и возвращаем результат
else {
# open(COMMAND, $command." 2>&1 |");
# local $/ = undef;
# $message = <COMMAND>;
# close(COMMAND);
$message = `$command 2>&1`;
$message = decode('utf-8', $message);
}
return $message;
}
# Функция обработки сообщений
sub on_message {
my $mid = shift || return;
my $msg = shift || return;
# Команда, которую будем выполнять
my $command = $msg->GetBody;
# Получаем JID отправителя
my $jid = new Net::XMPP::JID($msg->GetFrom)->GetJID("base");
# Перебираем админов
foreach my $admin (@admins) {
# Если сообщение от одного из них
if ($jid eq $admin) {
# Обрабатываем сообщение и посылаем ответ
my $reply = Net::Jabber::Message->new();
$reply->SetMessage(
'to' => $msg->GetFrom,
'body' => process_command($command),
);
$client->Send($reply);
}
}
}
# Цикл обработки сообщений
while (defined($client->Process)) {
}
# На всякий случай закрываем соединение
$client->Disconnect();
Скрипт настроен на работу с русским языком. Единственная проблемма, что он валится при любых бинарных символах, например: fl.
Конфиг для него должен находиться в пути /etc/jabber-shell.conf и выглядеть так: http://dpaste.org/z1Fu/
(
‘server’ => ‘jabber.org’, # Сервер для бота
‘port’ => ‘5222’, # Порт сервера для бота
‘username’ => ‘username’, # Имя пользователя на сервере
‘password’ => ‘password’, # Пароль аккаунта бота
‘resource’ => ‘jabber-shell’, # Ресур бота
‘admins’ => ‘pomatu@jabber.org’, # JID админов
)
Бот заканчивает работу, при первом вылете или дисконнекте, поэтому лучше сделать скрипт такого вида:
#!/bin/bash
while true
do
perl /path/to/perl/file/that/is/written/upper.pl
done
Согласен — это извращенно. Зато практично :)
Оффициальный сайт бота (без поддержки русского): http://jabber-shell.ylsoftware.com/