使用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重定向在远程系统上进行复制(我不想执行复制操作以将日志复制到本地系统)。如何实现此功能?

Answers:


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
正如Thomas Telensky指出的那样,根据您的需求,ssh最终会更容易。但是期望可以是完全非交互的。我假设您的意思是,telnet之后的所有行都是您想要在远程计算机上执行的行,在这种情况下,只需将它们作为发送命令添加到期望脚本中,然后删除interact命令。但是ssh更简单,更安全。
joemooney 2011年

2
很公平。我将使用期望来完成此任务。
可汗

1
另一个不错的补充是阅读此内容-elenako.com/2013/04/04/…,前提是脚本\r在命令末尾没有序列,并且当我单击Enter输入时,由于某种原因它没有起作用
llamerr

87

尽管我建议也使用Expect,但对于非交互式使用,普通的shell命令可能就足够了。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 |了两者,以便在屏幕上进行完整的会话;-)
paluh

1
就我而言,这是最有帮助的答案,但是我必须添加echo -e "command\r";
mf_

1
如何以非交互方式向telnet提供密码?
Geremia

{ echo "remotecommand 1"; echo "remotecommand 2"; sleep 1; } | telnet 10.1.1.1 :此示例符合我的要求。只想知道如果telnet失败并且shell脚本应该如何添加错误检查exit 1
Yash

44

学习HTTP协议时经常使用Telnet。我曾经将该脚本用作网络抓取工具的一部分:

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命令),并且只需要一个空的echo并在最后需要睡眠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使用“ expect”命令自动执行telnet登录。可以在这里找到更多信息:http : //osix.net/modules/article/?id=30

远程登录

#!/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的期望脚本。下例显示了如何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

以下对我有用...将您要远程登录的所有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(程序)可以用作任何(或更实际上是MOST)基于文本的客户端/服务器连接的客户端。它可以用于轻松测试,例如HTTP和IMAP。@Tomas的建议是用SSH代替Telnet(远程登录服务)的使用。尽管他的评论是正确的,但OP可能并不需要。
罗布·谢泼德

Rob,确实可以使用telnet连接到任何端口,但是请参见OP的问题-在他的上下文中,他只想使用telnet进行登录(引用:“在远程系统上执行某些命令”)。为此目的使用远程登录非常危险。
TMS

这不是使用他现有的脚本专门说“自动化一些与telnet相关的任务”的问题的答案。
FractalSpace

0

这是在bash shell / 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

tcpdumpwireshark,看看有什么命令发送到服务器本身

试试这个

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'3

1
并不是要侮辱,更像是……我不知道,道歉。我一直看到人们使用Expect命令作为解决方案。我只希望人们意识到有更好的解决方案来理解您要完成的任务。Expect命令不会向您显示其工作方式,只是一个不为人知的解决方法。那就更让人困惑了。如有疑问,请联系来源。如果源不可用,并且它的网络协议为tcpdump,wireshark,则监听数据包并按照命令流进行操作,您应该能够将一些知识与实际知识放在一起。
str8 2012年

7
如果您这么说-我是Mathematica程序员,那么您的回答和评论的实质对我来说是个谜。但是我并不是唯一一个将“白痴”这个词解释为故意侮辱的人。我认为您需要在网站上花费更多时间,看看人们在这里的行为。
Verbeia'3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.