bashスクリプトを使用したtelnetセッションの自動化


80

私は、Bashスクリプトを使用して、いくつかのtelnet関連タスクの自動化に取り組んでいます。自動化されると、ユーザーと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
'expect'は、主にインタラクティブセッション用です。私が欲しいのは、自動化された非対話型セッションです。私が直面している問題は、telnet 10.1.1.1に続くすべての行が、アクセスしているマシンではなくローカルマシンで実行されるため、リモートシステムで(telnet経由で)スクリプトを実行できないことです。
カーン2011

3
Thomas Telenskyが指摘したように、ニーズに応じてsshは最終的には簡単です。しかし、expectは完全に非対話型である可能性があります。telnetに続くすべての行がリモートマシンで実行したいものであることを意味していると思います。その場合は、sendコマンドとしてexpectスクリプトに追加し、interactコマンドを削除します。しかし、sshはより簡単で安全です。
joemooney 2011

2
けっこうだ。このタスクにはexpectを使用します。
カーン2011

1
もう1つの良い追加は、これを読むことです-elenako.com/2013/04/04/…、ただし\r、コマンドの最後にスクリプトにシーケンスがなく、[Enter]をクリックすると、何らかの理由で機能しません
llamerr

88

期待値を使用することもお勧めしますが、非対話型の使用には通常のシェルコマンドで十分な場合があります。Telnetはstdinでコマンドを受け入れるため、コマンドをパイプまたは書き込む必要があります。

telnet 10.1.1.1 <<EOF
remotecommand 1
remotecommand 2
EOF

(編集:コメントから判断すると、リモートコマンドは入力を処理するのに時間がかかるか、初期のSIGHUPがtelnetによって正常に取得されません。このような場合、入力で短いスリープを試すことができます:)

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

いずれにせよ、インタラクティブになる場合などは、を使用してくださいexpect


2
+1sleepは夢のよう| tee /dev/tty |に機能します;-)画面上でフルセッションを行うために間に追加しました
;

1
私の場合は、最も参考になっ答えが、私は追加する必要がありましたecho -e "command\r";
mf_

1
telnetに非対話的にパスワードを提供するにはどうすればよいですか?
ジェレミア

{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1 :この例は私の要件を満たしています。telnetが失敗し、シェルスクリプトが失敗した場合に、エラーチェックを追加する方法を知りたいだけですexit 1
ヤシュ

44

Telnetは、HTTPプロトコルを学ぶときによく使用されます。以前は、そのスクリプトをWebスクレイパーの一部として使用していました。

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 2014年


同等のワンライナー:{ echo "GET / HTTP/1.1"; echo "Host: www.example.com"; echo; sleep 1; } | telnet www.example.com 80。(openコマンドを使用しない限り)最初はスリープは不要であり、最後には2つではなく1つの空のエコーとスリープが必要であることに注意してください。
baptx

ただし、HTTPSリクエストを実行する必要がある場合は、netcat(ncatまたはncとも呼ばれます)を使用する必要があります。{ echo "GET / HTTP/1.1"; echo "Host: example.com"; echo; sleep 1; } | ncat --ssl example.com 443
baptx19年

12

これは私のために働いた。

ユーザー名とパスワードを必要とする複数のtelnetログインを自動化しようとしていました。さまざまなサーバーから自分のマシンにログを保存しているため、telnetセッションはバックグラウンドで無期限に実行する必要があります。

telnet.shは、「expect」コマンドを使用して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.shを実行することにより、各telnetセッションのバックグラウンドプロセスを作成するために使用されます。詳細については、コードのコメントセクションを参照してください。

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. コマンド 'screen -ls'を使用して、バックグラウンドで実行されている画面がないことを確認します。
  2. 読む http://www.gnu.org/software/screen/manual/screen.html#Stuffを画面とそのオプションについての詳細を読むために。
  3. sample_script.shの「-p」オプションは、特定のウィンドウを事前に選択して再接続し、「-X」オプションを介してコマンドを送信します。そうしないと、「画面セッションが見つかりません」というエラーが発生します。

2

bashでインストールされたexpectスクリプトを使用できます。以下の例は、パスワードのない組み込みボードにtelnexする方法を示しています

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

以下は私のために働いています...あなたがtelnetしたいすべての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 2013年

2
telnet(プログラム)は、任意の(またはより実際的にはMOST)テキストベースのクライアント/サーバー接続のクライアントとして使用できます。HTTPやIMAPなどの簡単なテストに使用できます。@Tomasの提案は、Telnet(リモートログインサービス)の使用をSSHに置き換えることです。彼のコメントは真実ですが、それはおそらくOPが要求していたものではありません。
ロブシェパード

ロブ、telnetは実際に任意のポートに接続するために使用できますが、OPの質問を参照してください-彼のコンテキストでは、ログインにのみtelnetを使用したいと考えています「リモートシステムでいくつかのコマンドを実行する」を引用)。この目的でtelnetを使用することは非常に危険です。
TMS

これは、彼の既存のスクリプトを使用して「いくつかのtelnet関連タスクを自動化する」という質問に対する答えではありません。
FractalSpace 2018

0

bashシェル/ expectでtelnetを使用する方法は次のとおりです

#!/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
新しさは無礼の言い訳にはなりません。FAQstackoverflow.com/faqをご覧ください。
verbeia 2012年

1
侮辱するつもりはなかった、もっと…わからない、お詫び。解決策としてexpectコマンドを使用している人々を見続けています。あなたが達成しようとしていることを理解するためのより良い解決策があることを人々に理解してもらいたいのです。expectコマンドは、その動作方法を示していません。わからない場合の回避策にすぎません。それはそうではないよりも混乱します。疑わしい場合は、ソースにアクセスしてください。ソースが利用できない場合、およびそのネットワークプロトコル、tcpdump、wiresharkがパケットをスヌープし、コマンドフローに従うと、実用的な知識で何かをまとめることができるはずです。
str8 2012年

7
あなたがそう言うなら-私はMathematicaプログラマーなので、あなたの答えとコメントの本質は私には謎です。しかし、「ばか」という言葉を意図的に侮辱していると解釈しているのは私だけではありません。このサイトでもう少し時間をかけて、人々がここでどのように行動するかを確認する必要があると思います。
verbeia 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.