Expect及Shell结合

Expect 是一个强大的自动化交互工具,特别适合处理需要用户交互的命令行程序。


一、Expect 核心详解

1. Expect 基本流程

  • spawn:启动目标程序
  • expect:等待特定模式出现
  • send:发送响应内容
  • interact(可选):将控制权交还用户

2. Expect常用命令

spawn

spawn ssh user@host     # 启动ssh连接
spawn ftp $ftp_host # 启动FTP连接

expect

expect {
   "password:" {send "mypass\r"} # 匹配password:
   "yes/no" {send "yes\r"; exp_continue} # 继续等待
  timeout {exit 1} # 超时处理
   eof {exit} # 程序结束
}

send

send "ls -l\r"              # 发送命令
send "exit\r" # 发送命令
send -- "$var\r" # 发送变量,--防止解释为选项

二、Expect脚本案例

案例1:自动SSH登录v1.0

#!/usr/bin/expect
spawn ssh root@10.9.48.121

expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "123\r" }
}

interact

案例2:自动SSH登录v2.0

#!/usr/bin/expect
set ip 10.9.48.121
set user root
set password 123
set timeout 5

spawn ssh $user@$ip

expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" }
}

interact

案例3:自动SSH登录v3.0

#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 5

spawn ssh $user@$ip

expect {
	"yes/no" { send "yes\r"; exp_continue }
	"password:" { send "$password\r" }
}

#interact
expect "#"
send "useradd alice\r"
send "pwd\r"
send "exit\r"
expect eof

[root@lichu ~]# ./expect_ssh_login_v3.sh 10.9.48.121 root 123
spawn ssh root@10.9.48.121
root@10.9.48.121's password: 
Last login: Thu Aug 14 16:46:30 2025 from 10.9.48.236
[root@nfs-server ~]# useradd alice
[root@nfs-server ~]# pwd
/root
[root@nfs-server ~]# exit
logout
Connection to 10.9.48.121 closed.

案例4:自动远程复制文件

#!/usr/bin/expect
set ip [lindex $argv 0]
set password [lindex $argv 1]
set timeout 5

#spawn rsync -av /etc/hosts root@$ip:/tmp
spawn scp -r /etc/hosts root@$ip:/tmp
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" };
}
expect eof

三、Expect 与 Shell 结合

1. 基本结合方式

方法1:在Shell中调用Expect脚本

#!/bin/bash
# 调用expect脚本并传递参数
./auto_ssh.exp $user $password $host

方法2:在Shell中嵌入Expect代码

#!/bin/bash

user="lichu"
pass="lichu123"
host="192.168.1.1"

/usr/bin/expect <<EOF

expect代码
expect代码
.........

expect eof
EOF

2. 结合实战案例

案例1:自动化批量SSH登录执行命令

[root@lichu ~]# vim remote_task.sh
#!/bin/bash
# remote_task.sh

hosts=("10.9.48.121" "10.9.48.200" "10.9.48.246" "server3")
user="lichu"
password="123"

for host in ${hosts[@]};
do
    if ! ping -c1 $host &>/dev/null;then
        echo "$host 不能连接,请检查"
        continue
    fi

    /usr/bin/expect <<EOF
    set timeout 20
    spawn ssh $user@$host
    expect {
        "yes/no" {send "yes\r"; exp_continue}
        "password:" {send "$password\r"}
         timeout {exit 1}
    }
    expect "$ " {send "df -h\r"}
    expect "$ " {send "free -m\r"}
    expect "$ " {send "exit\r"}
    expect eof
EOF
    echo "===== $host 检查完成 ====="
done

案例2:自动化批量rsync文件复制

[root@lichu ~]# cat hosts.txt 
10.9.48.121 root 123
10.9.48.246 lichu 123

[root@lichu ~]# vim remote_copy.sh
#!/usr/bin/bash
# remote_copy.sh
while read line
do
        {
        read host user password <<<$line
        /usr/bin/expect <<-EOF
        set timeout 5
        spawn rsync -va /etc $user@$host:/tmp
        expect {
                "yes/no" { send "yes\r"; exp_continue }
                "password:" { send "$password\r" }
        }
        expect eof
EOF
        }&
done < hosts.txt
wait
echo "all finish..."

案例3:自动化批量公钥推送

[root@lichu ~]# cat hosts.txt 
10.9.48.121 root 123
10.9.48.246 lichu 123

[root@lichu ~]# cat push_publickey.sh
#!/usr/bin/bash
# push_publickey.sh

rpm -q expect &>/dev/null
if [ $? -ne 0 ];then
        yum -y install expect
fi

if [ ! -f ~/.ssh/id_rsa ];then
        ssh-keygen -P "" -f ~/.ssh/id_rsa
fi

while read line
do
        {
        read host user password <<<$line
        ping -c1 $host &>/dev/null
        if [ $? -eq 0 ];then
                /usr/bin/expect <<-EOF
                set timeout 10
                spawn ssh-copy-id $user@$host
                expect {
                        "yes/no" { send "yes\r"; exp_continue }
                        "password:" { send "$password\r" }
                }
                expect eof
EOF
        fi
        }&
done < hosts.txt
wait
echo "finish......"


[root@lichu ~]# ssh root@10.9.48.121 'hostname'
nfs-server
[root@lichu ~]# ssh lichu@10.9.48.246 'hostname'
lichu

案例4:自动化FTP文件传输【扩展】

#!/bin/bash
# 文件名:auto_ftp.sh

ftp_host="ftp.example.com"
ftp_user="user"
ftp_pass="password"
local_file="/data/upload.txt"
remote_dir="/incoming"

/usr/bin/expect <<EOF
set timeout 60
spawn ftp $ftp_host
expect "Name*" {send "$ftp_user\r"}
expect "Password:" {send "$ftp_pass\r"}
expect "ftp>" {send "cd $remote_dir\r"}
expect "ftp>" {send "put $local_file\r"}
expect "ftp>" {send "bye\r"}
expect eof
EOF

if [ $? -eq 0 ]; then
   echo "文件上传成功"
else
   echo "文件上传失败"
fi

💡 感谢你读到这里!这篇《Expect及Shell结合》是我的用心分享,如果你觉得有收获,不妨:


点个「赞」或「分享」,让更多同路人相遇


🔍 关注我的博客,持续接收技术/成长类干货


💬 文末留言聊聊你的想法,或遇到的同类问题~


🔒 本文为原创,转载请保留原文链接(https://www.lichu228.top/archives/408)与作者信息,感谢尊重与支持!


🌐 想找更多优质内容?点击进入博客主页探索吧~


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇