автоматизація сеансу telnet за допомогою скриптів bash


80

Я працюю над автоматизацією деяких завдань, пов'язаних з telnet, за допомогою скриптів Bash. Після автоматизації не буде взаємодії користувача з telnet. (тобто це буде повністю автоматизовано)

сценарії виглядає приблизно так:

# execute some commands on the local system
# access a remote system with an IP address: 10.1.1.1 (for example)

telnet 10.1.1.1

# execute some commands on the remote system
# log all the activity (in a file) on the Local system
# exit telnet
# continue on with executing the rest of the script.

Тут я зіткнувся з 2 проблемами:

  1. Як виконувати команди на віддаленій системі зі сценарію (без взаємодії людини)?

    Зі свого досвіду з деякими тестовими кодами я зміг зробити висновок, що при запуску telnet 10.1.1.1 telnet переходить у інтерактивний сеанс, а наступні рядки коду в сценарії виконуються в локальній системі. Як запустити рядки коду на віддаленій системі, а не на локальній?

  2. Я не можу отримати файл журналу для активності в сеансі telnet у локальній системі. Перенаправлення stdout, яке я використовував, робить копію у віддаленій системі (я не хочу виконувати операцію копіювання для копіювання журналу в локальну систему). Як я можу досягти цієї функціональності?

Відповіді:


77

Напишіть expectсценарій.

Ось приклад:

#!/usr/bin/expect

#If it all goes pear shaped the script will timeout after 20 seconds.
set timeout 20
#First argument is assigned to the variable name
set name [lindex $argv 0]
#Second argument is assigned to the variable user
set user [lindex $argv 1]
#Third argument is assigned to the variable password
set password [lindex $argv 2]
#This spawns the telnet program and connects it to the variable name
spawn telnet $name 
#The script expects login
expect "login:" 
#The script sends the user variable
send "$user "
#The script expects Password
expect "Password:"
#The script sends the password variable
send "$password "
#This hands control of the keyboard over to you (Nice expect feature!)
interact

Бігти:

./myscript.expect name user password

2
"очікувати" в основному для інтерактивних сесій. Я хочу автоматизованого неінтерактивного сеансу. проблема, з якою я стикаюся, полягає в тому, що я не можу запустити сценарії у віддаленій системі (через telnet), оскільки всі рядки, що слідують за telnet 10.1.1.1 , виконуються на локальній машині, а не на машині, до якої я отримую доступ.
хан,

3
Як зазначив Томас Теленський, залежно від ваших потреб ssh, нарешті, простіше. Але очікування може бути абсолютно неінтерактивним. Я припускаю, що ви маєте на увазі, що всі рядки після telnet - це те, що ви хочете виконати на віддаленій машині; у такому випадку просто додайте їх до сценарію очікування як команди надсилання та видаліть команду interact. Але ssh простіше і безпечніше.
joemooney

2
досить справедливо. Я буду використовувати очікування для цього завдання.
хан

1
ще одним хорошим доповненням є прочитати це - elenako.com/2013/04/04/… , за умови, що сценарій не мав \rпослідовності в кінці команди, і коли я натиснув
клавішу

88

Хоча я б також запропонував використовувати очікування, для неінтерактивного використання може бути достатньо звичайних команд оболонки. Telnet приймає свою команду на stdin, тому вам просто потрібно перенести або записати в неї команди:

telnet 10.1.1.1 <<EOF
remotecommand 1
remotecommand 2
EOF

(Редагувати: судячи з коментарів, віддаленій команді потрібно деякий час для обробки входів, або телнет не сприймає ранній SIGHUP. У цих випадках ви можете спробувати короткий сон на вході :)

{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1

У будь-якому випадку, якщо він стає інтерактивним або чимсь іншим, використовуйте expect.


2
+1 sleepпрацює як мрія ;-) Я також додав | tee /dev/tty |між ними, щоб мати повний сеанс на екрані ;-)
paluh

1
у моєму випадку echo -e "command\r";
найкорисніша

1
Як надати пароль telnet неінтерактивно?
Джеремия

{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1 : Цей приклад відповідає моїм вимогам. Просто хочу знати, як ми додаємо перевірку помилок, якщо telnet не працює, а сценарій оболонки повинен exit 1.
Яш

44

Telnet часто використовується, коли ви вивчаєте протокол HTTP. Раніше я використовував цей сценарій як частину свого веб-скрепера:

echo "open www.example.com 80" 
sleep 2 
echo "GET /index.html HTTP/1.1" 
echo "Host: www.example.com" 
echo 
echo 
sleep 2

припустимо, що назва сценарію - get-page.sh, тоді:

get-page.sh | telnet

дасть вам HTML-документ.

Сподіваюся, це комусь буде корисно;)


1
Найкорисніший коментар! Це насправді дозволяє автоматизувати надсилання команд, вводячи їх у цикл
RomanM

Ще одне довідкове повідомлення blog.tonycode.com/tech-stuff/http-notes/…
leomeurer

Один лайнер еквівалент: { echo "GET / HTTP/1.1"; echo "Host: www.example.com"; echo; sleep 1; } | telnet www.example.com 80. Зверніть увагу, що сон не потрібен на початку (якщо ви не використовуєте команду відкрити), і що в кінці потрібно лише одне порожнє ехо та сон 1 замість 2.
baptx

Але якщо вам потрібно зробити HTTPS-запити, ви повинні використовувати netcat, також відомий як ncat або nc:{ echo "GET / HTTP/1.1"; echo "Host: example.com"; echo; sleep 1; } | ncat --ssl example.com 443
baptx

12

Це спрацювало для мене ..

Я намагався автоматизувати кілька логінів telnet, для яких потрібні ім’я користувача та пароль. Сеанс telnet повинен виконуватися у фоновому режимі безкінечно, оскільки я зберігаю журнали з різних серверів на своєму комп'ютері.

telnet.sh автоматизує вхід в telnet за допомогою команди 'очікувати'. Більше інформації можна знайти тут: http://osix.net/modules/article/?id=30

telnet.sh

#!/usr/bin/expect
set timeout 20
set hostName [lindex $argv 0]
set userName [lindex $argv 1]
set password [lindex $argv 2]

spawn telnet $hostName

expect "User Access Verification"
expect "Username:"
send "$userName\r"
expect "Password:"
send "$password\r";
interact

sample_script.sh використовується для створення фонового процесу для кожного з сеансів telnet шляхом запуску telnet.sh. Більше інформації можна знайти в розділі коментарів коду.

sample_script.sh

#!/bin/bash
#start screen in detached mode with session-name 'default_session' 
screen -dmS default_session -t screen_name 
#save the generated logs in a log file 'abc.log' 
screen -S default_session -p screen_name -X stuff "script -f /tmp/abc.log $(printf \\r)"
#start the telnet session and generate logs
screen -S default_session -p screen_name -X stuff "expect telnet.sh hostname username password $(printf \\r)"
  1. Переконайтесь, що у backgroud не запущено екран, використовуючи команду 'screen -ls'.
  2. Прочитайте http://www.gnu.org/software/screen/manual/screen.html#Stuff, щоб прочитати більше про екран та його параметри.
  3. Параметр "-p" у вибірці sample_script.sh попередньо вибирає та повторно приєднує до певного вікна, щоб надіслати команду за допомогою опції "-X", інакше з'являється помилка "Не знайдено сеанс екрану".

2

Ви можете використовувати очікувані сценарії, встановлені з bash. Нижче на прикладі показано, як здійснити телнекс на вбудовану плату без пароля

#!/usr/bin/expect

set ip "<ip>"

spawn "/bin/bash"
send "telnet $ip\r"
expect "'^]'."
send "\r"
expect "#"
sleep 2

send "ls\r"
expect "#"

sleep 2
send -- "^]\r"
expect "telnet>"
send  "quit\r"
expect eof

2

Для мене працює наступне ... розмістіть усі свої IP-адреси, які ви хочете зателефонувати, в IP_sheet.txt

while true
read a
do
{
    sleep 3
    echo df -kh
    sleep 3
    echo exit
} | telnet $a
done<IP_sheet.txt

1
#!/bin/bash
ping_count="4"
avg_max_limit="1500"
router="sagemcom-fast-2804-v2"
adress="192.168.1.1"
user="admin"
pass="admin"

VAR=$(
expect -c " 
        set timeout 3
        spawn telnet "$adress"
        expect \"Login:\" 
        send \"$user\n\"
        expect \"Password:\"
        send \"$pass\n\"
        expect \"commands.\"
        send \"ping ya.ru -c $ping_count\n\"
        set timeout 9
        expect \"transmitted\"
        send \"exit\"
        ")

count_ping=$(echo "$VAR" | grep packets | cut -c 1)
avg_ms=$(echo "$VAR" | grep round-trip | cut -d '/' -f 4 | cut -d '.' -f 1)

echo "1_____ping___$count_ping|||____$avg_ms"
echo "$VAR"

0

Для цього використовуйте ssh. Створіть ключі без використання пароля та розмістіть його у .authorized_keys на віддаленій машині. Створіть сценарій для запуску віддалено, скопіюйте його на іншу машину, а потім просто запустіть його віддалено за допомогою ssh.

Я багато разів використовував цей підхід з великим успіхом. Також зверніть увагу, що він набагато безпечніший, ніж telnet.


1
sshБезперечно, більш безпечний, ніж telnet, але деякі IP-пристрої просто не надають sshпослуги і покладаються на telnetпротокол використання пристрою.
fduff

2
telnet (програма) може використовуватися як клієнт для БУДЬ-ЯКОГО (або більш практично БЕЗКОШТОВНО) текстових з'єднань клієнт-сервер. Його можна використовувати для простого тестування, наприклад, HTTP та IMAP. Пропозиція @Tomas полягає в тому, щоб замінити використання Telnet (служби віддаленого входу) на SSH. хоча його коментар відповідає дійсності, це, мабуть, не те, що вимагав ОП.
Роб Шеперд

Роб, telnet дійсно можна використовувати для підключення до будь-якого порту, але дивіться питання OP - у його контексті він хоче використовувати telnet лише для входу (цитуючи: "виконати деякі команди у віддаленій системі" ). Використання telnet для цієї мети є дуже ризикованим.
TMS

Це не відповідь на запитання, яке конкретно говорить про "автоматизацію деяких завдань, пов'язаних з telnet", використовуючи його існуючі сценарії.
FractalSpace

0

Ось як використовувати telnet в оболонці bash / очікувати

#!/usr/bin/expect
# just do a chmod 755 one the script
# ./YOUR_SCRIPT_NAME.sh $YOUHOST $PORT
# if you get "Escape character is '^]'" as the output it means got connected otherwise it has failed

set ip [lindex $argv 0]
set port [lindex $argv 1]

set timeout 5
spawn telnet $ip $port
expect "'^]'."

0

Сценарій для отримання версії CISCO-серверів:

#!/bin/sh

servers='
192.168.34.1
192.168.34.3
192.168.34.2
192.168.34.3
'
user='cisco_login'
pass='cisco_password'

show_version() {
host=$1
expect << EOF
set timeout 20
set host $host
set user $user
set pass $pass
spawn telnet $host
expect "Username:"
send "$user\r"
expect "Password:"
send "$pass\r"
expect -re ".*#"
send "show version\r"
expect -re ".*-More-.*"
send " "
expect -re ".*#"
send "exit\r"
EOF
}

for ip in $servers; do
  echo '---------------------------------------------'
  echo "$ip"
  show_version $ip | grep -A3 'SW Version'
done

-4

Пограйте з tcpdumpабо wiresharkі подивіться, які команди надсилаються на сам сервер

Спробуйте це

printf (printf "$username\r\n$password\r\nwhoami\r\nexit\r\n") | ncat $target 23

Деякі сервери вимагають затримки з паролем, оскільки він не містить рядків у стеку

printf (printf "$username\r\n";sleep 1;printf "$password\r\nwhoami\r\nexit\r\n") | ncat $target 23**

9
Новизна - це не виправдання хамству. Перегляньте поширені запитання stackoverflow.com/faq .
Verbeia

1
не було призначено ображати, більше схоже на ... я не знаю, вибачення. Я просто продовжую бачити людей, які використовують команду очікування як рішення. Я просто хочу, щоб люди зрозуміли, що є краще рішення для розуміння того, що ви намагаєтесь досягти. Команда очікувань не показує вам, як це працює, це просто обхідний шлях для невідомості. Це більше бентежить, ніж ні. Якщо ви сумніваєтесь, перейдіть до джерела. Якщо джерело недоступне, і якщо це мережевий протокол, tcpdump, wireshark, переглядайте пакети та дотримуйтесь командного потоку, і ви зможете щось поєднати з робочими знаннями.
str8

7
Якщо ви так говорите - я програміст Mathematica, тому суть вашої відповіді та коментаря для мене загадка. Але я не самотня, трактуючи слово "ідіоти" як навмисне образливе. Я думаю, вам потрібно провести трохи більше часу на сайті і подивитися, як люди тут поводяться.
Verbeia
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.