Архив метки: терминал

Автоматизация Telnet/SSH

Одна из часто встречающихся задач администрирования — автоматизация терминальной рутины; иными словами, действий, выполняемых через Telnet или SSH.

Tmagic

На сайте IBM есть такая вещь, как Terminal Automation Tool (Tmagic). Вот пример скрипта, который она может выполнить:

* Variables declared below.
V host=host1
V port=23
V user=user1
V password=user1
V prompt="$ "* Variable with special meaning
V ThinkTime=2
V TimeOut=2
V NumThreads=2
V LogSeed="TMagic"
V LogPath="/tmp"

* Connect and logon
C "${host} ${port}"R "login"
S "${user}\r"
R "Password"
S "${password}\r"
R "${prompt}"
L "Logged in.\n"

* A simple "date" command
FOR 5 TIMES DO
S "date\r"
R "${prompt}"
D 1
DONE
L "All Done\n"

Q

Как видим, здесь происходит подключение к хосту и выполнение на нем неких команд. Результаты работы записываются в лог. Если этого достаточно, можно идти и скачивать. Небольшая инструкция входит в комплект.

Expect

Expect, расширение языка Tcl — куда более мощный инструмент.

Я скачивал в исходниках expect-5.43.0-5.1.src.rpm и компилировал. Потребуется установить собственно expect, tcl и tcl.src. Поскольку все это может оказаться в довольно неожиданных каталогах, могут потребоваться дополнительные параметры для configure. Здесь tclconfig — это местонахождение tclConfig.sh, tclinclude — понятно, исходников tcl.

./configure --with-tclconfig=/usr/lib --with-tclinclude=/usr/src/redhat/SOURCES/tcl8.4.13

Потом как обычно, make и make install.

Вот скрипт, близкий к тому, что я реально использую для автоматизации одной из задач:

#!/usr/local/bin/expect -f
# --------------------------------------
# Usage: expect-script [host] [username]
# --------------------------------------
# Variables
set host [lrange $argv 0 0]
set user [lrange $argv 1 1]
set timeout -1# Connect to remote host
spawn ssh $user@$host
match_max 100000

# Wait for password prompt
expect "*?assword:*"

# Grab the password without showing it
stty -echo
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set password $expect_out(1,string)

# ...and then send it
send -- "$password\r"
send_user "\n"

# Wait for command prompt
expect -re "(%|#|\\$) $"

# Send actual commands
send "command1\r"
send "command2\r"
send "A"
send "B"
send "C"

# Leave control to the user
interact

Здесь тоже все вполне понятно: из командной строки берутся два аргумента — имя хоста и имя пользователя, затем мы подключаемся к хосту по SSH, запрашиваем пароль у пользователя (на экране он не будет отображаться), посылаем пароль, ждем появления командной строки и посылаем некоторые команды и нажатия клавиш. В конце мы отдаем управление терминалом пользователю.

Разумеется, фазу ввода пароля можно исключить:

set password MyPaSsWoRd
expect "*?assword:*"
send -- "$password\r"
send_user "\n"
expect -re "(%|#|\\$) $"

Тогда пароль будет фигурировать в скрипте в открытом виде. Можно пойти правильным путем, отказаться от паролей в пользу ключей и применить ssh-agent/ssh-add, и это отдельная тема.

Приведенный скрипт я использую совместно с другим, который сначала запускает GNOME Terminal с нужной кодировкой:

export LANG=ru_RU.IBM866; gnome-terminal --disable-factory --execute /scripts/expect-script hostname username

Более подробно о настройке GNOME Terminal речь шла в предыдущей заметке: GNOME Terminal: кодировка по умолчанию.

Способ скрытия пароля при вводе взят отсюда: http://stackoverflow.com/questions/681928/how-can-i-make-an-expect-script-prompt-for-a-password

GNOME Terminal: кодировка по умолчанию

В GNOME Terminal нет штатных средств, чтобы установить какую-либо кодировку по умолчанию. Можно только поменять текущую кодировку через меню (Терминал → Установить кодировку символов).

Заметим, что при запуске терминала устанавливается кодировка текущей локали. Таким образом, задачу можно решить, поменяв локаль перед запуском терминала.

Допустим, нас интересует кодировка CP866 (IBM866). Нужно, чтобы существовала соответствующая локаль. Система в данном случае — RHEL 5.5. Посмотрим, какие у нас есть локали:

locale -a

Если локали с кодировкой IBM866 нет, создадим ее.

localedef --no-archive -c -i ru_RU -f IBM866 ru_RU.IBM866

Теперь можно запускать терминал, примерно так:

export LANG=ru_RU.IBM866; gnome-terminal --disable-factory

Кстати, можно сразу задать скрипт, который следует выполнить при запуске:

export LANG=ru_RU.IBM866; gnome-terminal --disable-factory --execute /scripts/script.sh

Впрочем, вопросы автоматизации терминала — это уже тема следующей заметки. Здесь же отмечу еще, что на случай, если потребуется использовать особый шрифт или еще какие-нибудь настройки, отличающиеся от стандартных, в GNOME Terminal есть возможность создать несколько профилей (Правка → Профили) и выбирать из них нужный при запуске из скрипта, например:

export LANG=ru_RU.IBM866; gnome-terminal --disable-factory --window-with-profile=MyCustomProfile