automatyzacja sesji telnet za pomocą skryptów bash


80

Pracuję nad automatyzacją niektórych zadań związanych z telnetem, używając skryptów Bash. Po zautomatyzowaniu nie będzie interakcji użytkownika z telnetem. (to znaczy będzie całkowicie zautomatyzowany)

skrypty wyglądają mniej więcej tak:

# 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.

Mam tu dwa problemy:

  1. Jak wykonywać polecenia w systemie zdalnym ze skryptu (bez udziału człowieka)?

    Na podstawie mojego doświadczenia z niektórymi kodami testowymi byłem w stanie wywnioskować, że po wykonaniu telnetu 10.1.1.1 telnet przechodzi do sesji interaktywnej, a kolejne wiersze kodu w skrypcie są wykonywane w systemie lokalnym. Jak mogę uruchomić linie kodu w systemie zdalnym, a nie lokalnym?

  2. Nie mogę uzyskać pliku dziennika dotyczącego aktywności w sesji telnet w systemie lokalnym. Przekierowanie stdout, którego użyłem, tworzy kopię w systemie zdalnym (nie chcę wykonywać operacji kopiowania w celu skopiowania dziennika do systemu lokalnego). Jak mogę osiągnąć tę funkcjonalność?

Odpowiedzi:


77

Napisz expectscenariusz.

Oto przykład:

#!/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

Biegać:

./myscript.expect name user password

2
„oczekiwanie” dotyczy głównie sesji interaktywnych. To, czego chcę, to automatyczna sesja nieinteraktywna. Problem, z którym się zmagam, polega na tym, że nie mogę uruchomić skryptów w systemie zdalnym (przez telnet), ponieważ wszystkie wiersze następujące po telnecie 10.1.1.1 są wykonywane na komputerze lokalnym, a nie na komputerze, do którego mam dostęp.
khan

3
Jak zauważył Thomas Telensky, w zależności od potrzeb ssh jest ostatecznie łatwiejsze. Ale oczekiwanie może być całkowicie nieinteraktywne. Zakładam, że masz na myśli, że wszystkie wiersze następujące po telnecie są tym, co chcesz wykonać na zdalnej maszynie, w takim przypadku po prostu dodaj je do skryptu oczekiwania jako polecenia wysyłania i usuń polecenie interakcji. Ale ssh jest łatwiejsze i bezpieczniejsze.
joemooney

2
Słusznie. Będę używał oczekiwania do tego zadania.
khan

1
kolejnym dobrym dodatkiem jest przeczytanie tego - elenako.com/2013/04/04/… , pod warunkiem, że skrypt nie miał \rsekwencji na końcu polecenia, a kiedy kliknąłem enter siebie, z jakiegoś powodu nie zadziałał
llamerr

88

Chociaż sugerowałbym również użycie oczekiwania, w przypadku użycia nieinteraktywnego mogą wystarczyć zwykłe polecenia powłoki. Telnet akceptuje swoje polecenie na stdin, więc wystarczy potokować lub wpisać do niego polecenia:

telnet 10.1.1.1 <<EOF
remotecommand 1
remotecommand 2
EOF

(Edycja: Sądząc po komentarzach, zdalne polecenie potrzebuje trochę czasu na przetworzenie danych wejściowych lub wczesne SIGHUP nie jest wdzięcznie pobierane przez telnet. W takich przypadkach możesz spróbować krótkiego snu na wejściu :)

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

W każdym razie, jeśli staje się interaktywny lub cokolwiek, użyj expect.


2
+1 sleepdziała jak sen ;-) Dodałem też | tee /dev/tty |pomiędzy, aby mieć pełną sesję na ekranie ;-)
paluh

1
w moim przypadku najbardziej pomocna odpowiedź, ale musiałem dodaćecho -e "command\r";
mf_

1
Jak podać hasło do usługi Telnet w trybie nieinteraktywnym?
Geremia

{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1 : Ten przykład spełnia moje wymagania. Chcę tylko wiedzieć, jak dodać funkcję sprawdzania błędów, jeśli telnet się nie powiedzie, a skrypt powłoki powinien exit 1.
Yash

44

Telnet jest często używany podczas nauki protokołu HTTP. Używałem tego skryptu jako części mojego skrobaka internetowego:

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

powiedzmy, że nazwa skryptu to get-page.sh wtedy:

get-page.sh | telnet

dostaniesz dokument html.

Mam nadzieję, że komuś to pomoże;)


1
Najbardziej pomocny komentarz! To faktycznie pozwala zautomatyzować wysyłanie poleceń, umieszczając je w pętli
RomanM


Równoważny jednej liniowej: { echo "GET / HTTP/1.1"; echo "Host: www.example.com"; echo; sleep 1; } | telnet www.example.com 80. Zauważ, że uśpienie nie jest potrzebne na początku (chyba że używasz polecenia open) i że na końcu potrzebne jest tylko jedno puste echo i uśpienie 1 zamiast 2.
baptx

Ale jeśli potrzebujesz wykonywać żądania HTTPS, powinieneś użyć netcat, znanego również jako ncat lub nc:{ echo "GET / HTTP/1.1"; echo "Host: example.com"; echo; sleep 1; } | ncat --ssl example.com 443
baptx

12

To zadziałało dla mnie ...

Próbowałem zautomatyzować wielokrotne logowania przez telnet, które wymagają nazwy użytkownika i hasła. Sesja telnet musi działać w tle przez czas nieokreślony, ponieważ zapisuję dzienniki z różnych serwerów na moim komputerze.

telnet.sh automatyzuje logowanie przez telnet za pomocą polecenia „oczekiwać”. Więcej informacji można znaleźć tutaj: 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 służy do tworzenia procesu w tle dla każdej sesji telnet poprzez uruchomienie telnet.sh. Więcej informacji można znaleźć w sekcji komentarzy w kodzie.

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. Upewnij się, że w tle nie działa żaden ekran, używając polecenia „screen -ls”.
  2. Przeczytaj http://www.gnu.org/software/screen/manual/screen.html#Stuff, aby dowiedzieć się więcej o ekranie i jego opcjach.
  3. Opcja „-p” w sample_script.sh wstępnie wybiera i ponownie podłącza do określonego okna, aby wysłać polecenie za pomocą opcji „-X”, w przeciwnym razie pojawi się błąd „Nie znaleziono sesji ekranu”.

2

Możesz używać oczekiwanych skryptów zamiast basha. Poniższy przykład pokazuje, jak telnex na wbudowaną płytkę bez hasła

#!/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

Następujące działa dla mnie ... umieść wszystkie swoje adresy IP, które chcesz telnetować w 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

W tym celu użyj ssh. Generuj klucze bez użycia hasła i umieść je w .authorized_keys na zdalnym komputerze. Utwórz skrypt do zdalnego uruchomienia, skopiuj go na inną maszynę, a następnie po prostu uruchom zdalnie za pomocą ssh.

Wielokrotnie stosowałem to podejście z dużym sukcesem. Należy również pamiętać, że jest znacznie bezpieczniejszy niż telnet.


1
sshjest z pewnością bezpieczniejszy niż telnet, ale niektóre urządzenia IP po prostu nie zapewniają sshusługi i polegają na telnetprotokole do korzystania z urządzenia.
fduff

2
telnet (program) może być używany jako klient dla KAŻDEGO (lub bardziej praktycznie WIĘKSZOŚCI) tekstowych połączeń klient / serwer. Może być używany do łatwego testowania, na przykład HTTP i IMAP. @Tomas sugeruje, aby zastąpić Telnet (usługę zdalnego logowania) przez SSH. chociaż jego komentarz jest prawdziwy, prawdopodobnie nie tego wymagał PO.
Rob Shepherd

Rob, telnet może być rzeczywiście używany do łączenia się z dowolnym portem, ale spójrz na pytanie OP - w tym kontekście chce używać telnetu tylko do logowania (cytując: "wykonaj niektóre polecenia w systemie zdalnym" ). Używanie telnetu do tego celu jest bardzo ryzykowne.
TMS

Nie jest to odpowiedź na pytanie, które konkretnie mówi „automatyzacja niektórych zadań związanych z telnetem” przy użyciu jego istniejących skryptów.
FractalSpace

0

Oto jak używać telnetu w powłoce bash / oczekiwać

#!/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

Skrypt do uzyskania wersji serwerów 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

Graj z tcpdumplub wiresharki zobacz, jakie polecenia są wysyłane do samego serwera

Spróbuj tego

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

Niektóre serwery wymagają opóźnienia z hasłem, ponieważ nie przechowuje linii na stosie

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

9
Nowość nie jest wymówką dla chamstwa. Zobacz FAQ stackoverflow.com/faq .
Verbeia,

1
nie miało być obraźliwe, bardziej jak ... nie wiem, przepraszam. Po prostu ciągle widzę ludzi używających polecenia oczekuj jako rozwiązania. Chcę tylko, żeby ludzie zdali sobie sprawę, że istnieje lepsze rozwiązanie, aby zrozumieć, co próbujesz osiągnąć. Polecenie oczekuj nie pokazuje, jak działa, jest to tylko obejście problemu, aby nie wiedzieć. Jest to bardziej zagmatwane niż nie. W razie wątpliwości udaj się do źródła. Jeśli źródło nie jest dostępne i jest to protokół sieciowy, tcpdump, wireshark, przeszukaj pakiety i postępuj zgodnie z przepływem poleceń, a powinieneś być w stanie połączyć coś razem z praktyczną wiedzą.
str.

7
Jeśli tak mówisz - jestem programistą Mathematica, więc treść Twojej odpowiedzi i komentarza jest dla mnie tajemnicą. Ale nie ja sam interpretuję słowo „idioci” jako celowo obraźliwe. Myślę, że musisz spędzić trochę więcej czasu na stronie i zobaczyć, jak ludzie się tutaj zachowują.
Verbeia,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.