Автоматизация 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

  • SuperMario

    а можно сделать, чтобы из батника работало?

  • http://ogarkov.com/ Дмитрий Огарков

    Поясните, что вы имеете в виду...