linux免交互登陆远程主机并执行命令(密钥对和Expect)

本文详细介绍了在Linux环境下实现免交互登录的两种方法:SSH无密码认证和利用expect工具自动执行交互任务。通过生成密钥对和配置SSH服务,或使用expect脚本,可以实现自动化登录和执行远程命令。

Linux下实现免交互登陆一般有两种:

1. SSH无密码认证方式

    客户端使用ssh-keygen生成密钥对,将公钥复制到服务端(authorized_keys),SSH提供公钥登陆,当SSH访问服务端时,服务端先在本机寻找客户端的公钥,然后把客户端发来的公钥进行比较,如果一致,则用公钥加密给客户端,客户端再用私钥进行解密,实现加密所有传输的数据。

1>.在客户机上创建密钥对

# ssh-keygen -t rsa #一路回车

2>.登陆ssh服务器,创建.ssh目录及设置权限

# mkdir /root/.ssh

# chmod 700 /root/.ssh

3>.将公钥上传到服务器并重命名为authorized.keys

# scp /root/.ssh/id_rsa.pub root@服务端IP:/root/.ssh/authorized_keys #id_rsa.pub可以追加多个客户端的公钥

4>.设置ssh服务器

# vi /etc/ssh/sshd_config

RSAAuthentication yes           #这三行取消注释,开启密钥对验证

PubkeyAuthentication yes

AuthorizedKeysFile .ssh/authorized_keys

PasswordAuthentication no    #关闭密码验证

# service sshd restart

5>.免交互登陆测试,并查看远程主机磁盘分区

# ssh root@服务端IP 'df -h'

 

2. 利用expect工具自动实现交互任务

   Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。

   CentOS安装:yum install expect

   Ubuntu安装:sudo apt-get install expect

1>.免交互登陆,查看远程主机磁盘分区

#!/usr/bin/expect

set ip 192.168.1.156

set pass 123.com    

set timeout 30

spawn ssh root@$ip

expect {

        "(yes/no)" {send "yes\r"; exp_continue}

        "password:" {send "$pass\r"}

}

expect "root@*"  {send "df -h\r"}

expect "root@*"  {send "exit\r"}

expect eof

# interact

2>.在Shell脚本中嵌入Expect语法

 方法1:使用EOF,将内容段让expect执行

#!/bin/bash

user=root

pass='123'

ip='192.168.1.154'

/usr/bin/expect << EOF

set timeout 30

spawn ssh $user@$ip   

expect {

        "(yes/no)" {send "yes\r"; exp_continue}

        "password:" {send "$pass\r"}

}

expect "root@*"  {send "df -h\r"}

expect "root@*"  {send "exit\r"}

expect eof

EOF

#!/bin/bash

user=root

pass='123'

ip='192.168.1.154'

expect -c "

    spawn ssh $user@$ip

    expect {

        \"(yes/no)\" {send \"yes\r\"; exp_continue}

        \"password:\" {send \"$pass\r\"; exp_continue}

        \"root@*\" {send \"df -h\r exit\r\"; exp_continue}

    }"

方法2:将expect脚本独立出来

# vi login.exp      #免交互登陆脚本

#!/usr/bin/expect

set ipaddress [lindex $argv 0]

set username [lindex $argv 1]

set password [lindex $argv 2]

if { $argc != 3 } {

puts "Usage: expect login.exp ipaddress username password"

exit 1

}

set timeout 30

spawn ssh $username@$ipaddress

expect {

        "(yes/no)" {send "yes\r"; exp_continue}

        "password:" {send "$password\r"}

}

expect "$username@*"  {send "df -h\r"}

expect "$username@*"  {send "exit\r"}

expect eof

# vi user_info     #用户信息文件

192.168.1.156   user    user

192.168.1.154   root    123.com

# vi expect.sh     #读取用户信息并赋值到变量

#!/bin/bash

for ip in `awk '{print $1}' user_info`

do

    user=`awk -v I="$ip" '{if(I==$1)print $2}' user_info`

    pass=`awk -v I="$ip" '{if(I==$1)print $3}' user_info`

    expect login.exp $ip $user $pass

done

参数说明:

set:可以设置超时,也可以设置变量

timeout:expect超时等待时间,默认10S

spawn:执行一个命令

expect "":匹配输出的内容

exp_continue:继续执行下面匹配

\r:可以理解为回车

$argc:统计位置参数数量

[lindex $argv 0]:脚本后第一个参数,类似于shell中$1,以此类推

puts:打印字符串,类似于echo

awk -v I="$ip":赋值变量

expect{...}:输入多行记录

其他参数说明:

timeout -1:永不超时退出

log_file /var/log/expect.log:记录交互信息,一般crontab时使用

interact:交互后不退出远程终端,如果加要把expect "root@*" {send "exit\r"}注释掉,如果不加,就直接退出

将spawn ssh root@$ip换成spawn ssh -o StrictHostKeyChecking=no root@ip既不会再提示是否将服务器计算机密钥加入本地known_hosts

From http://blog.51cto.com/lizhenliang/1607723

<think>嗯,用户问的是如何在shell脚本中用ssh远程执行命令,使用abc用户对应的密码登录。这个问题看起来挺常见的,但实际处理起来有几个需要注意的地方。首先,我需要回忆一下ssh命令的基本用法。通常,ssh登录的命令是`ssh user@host`,然后会提示输入密码。但是在脚本中自动输入密码就比较麻烦了,因为ssh默认不支持直接在命令行里写密码,这是出于安全考虑。 那用户的需求是在脚本中自动以abc用户密码登录,然后执行命令。这时候,常见的解决方案可能有几种。首先想到的是sshpass工具,它允许在命令行中指定密码。但需要先安装这个工具,可能有些系统默认没有安装。比如在Ubuntu上可以用apt安装,CentOS用yum或者dnf。不过,用户的环境可能不同,需要考虑到这一点。 另外,还有一种方法是使用expect脚本,它可以模拟用户输入密码的过程。但expect需要额外的脚本编写,可能对新手来说有点复杂。不过,用户可能更倾向于简单的解决方案,所以sshpass可能是更直接的选择。 然后需要给出具体的命令示例。比如使用sshpass的话,命令大概是`sshpass -p '密码' ssh abc@host '命令'`。但要注意密码中包含特殊字符的情况,可能需要转义或者使用引号包裹。此外,安全方面的问题也需要提醒用户,因为在脚本中明文存储密码有风险,建议使用密钥认证或者其他更安全的方式。 还有,用户可能没有提到的是,如果远程主机的指纹没有保存在本地known_hosts文件中,第一次连接时会提示确认,这会导致脚本中断。所以可能需要加上`-o StrictHostKeyChecking=no`选项来跳过确认,不过这也带来潜在的安全风险,需要权衡。 另外,有没有其他方法?比如配置SSH密钥对,这样可以免密登录,更安全。但用户可能因为某些原因必须使用密码,比如临时任务或者没有权限配置密钥。这时候还是得用sshpass或者expect。 再考虑一下不同系统下的兼容性,比如macOS上安装sshpass可能比较麻烦,需要brew安装,而Linux发行版通常有包管理直接安装。用户可能是在Linux环境下,但最好还是提到不同系统的安装方法。 然后,写出具体的脚本示例,包括安装sshpass的步骤,执行命令的例子,以及注意事项。比如: #!/bin/bash sshpass -p 'abc密码' ssh -o StrictHostKeyChecking=no abc@远程主机 "要执行的命令" 同时提醒用户,如果命令中有特殊符号,可能需要用引号包裹,或者转义处理。此外,安全建议部分要强调密码明文的风险,推荐使用密钥认证,给出生成密钥对复制的命令,比如ssh-keygenssh-copy-id。 总结一下,回答的结构应该是先介绍sshpass的方法,包括安装示例,然后提到expect的替代方案,最后推荐更安全的密钥认证方式。同时,注意事项部分涵盖安全警告、首次连接确认、特殊字符处理等。这样用户可以根据自己的情况选择合适的方法,了解潜在的风险更好的替代方案。</think>在Shell脚本中使用SSH远程执行命令通过密码认证登录,可以通过以下步骤实现: --- ### 一、基础方法:使用 `sshpass` 工具 #### 1. 安装 `sshpass` - **Ubuntu/Debian**: ```bash sudo apt-get install sshpass ``` - **CentOS/RHEL**: ```bash sudo yum install sshpass ``` #### 2. 脚本示例 ```bash #!/bin/bash # 定义变量 HOST="远程主机IP或域名" USER="abc" PASSWORD="abc的密码" COMMAND="要执行的命令(如:echo 'Hello' > /tmp/test.txt)" # 通过sshpass传递密码登录执行命令 sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no $USER@$HOST "$COMMAND" ``` #### 参数说明: - `-p "$PASSWORD"`:直接指定密码(需安装sshpass) - `-o StrictHostKeyChecking=no`:跳过首次连接时的SSH指纹确认提示 --- ### 二、替代方法:使用 `expect` 自动化交互 如果无法使用 `sshpass`,可以通过 `expect` 脚本模拟终端输入: #### 1. 安装 `expect` ```bash sudo apt-get install expect # Ubuntu/Debian sudo yum install expect # CentOS/RHEL ``` #### 2. 脚本示例 ```bash #!/usr/bin/expect set HOST "远程主机IP或域名" set USER "abc" set PASSWORD "abc的密码" set COMMAND "要执行的命令" spawn ssh $USER@$HOST "$COMMAND" expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "$PASSWORD\r" } } expect eof ``` --- ### 三、安全建议(⚠️ 重要!) 1. **密码明文风险**: - 密码直接写在脚本中会暴露敏感信息,建议仅在测试环境使用。 - 生产环境推荐使用 **SSH密钥认证**(见下文)。 2. **首次连接确认问题**: - 如果远程主机是首次连接,需手动执行一次SSH登录接受指纹,或在脚本中添加 `-o StrictHostKeyChecking=no`(会降低安全性)。 --- ### 四、推荐方案:SSH密钥认证(更安全) #### 1. 生成密钥对 ```bash ssh-keygen -t rsa # 生成后密钥保存在 ~/.ssh/id_rsa ~/.ssh/id_rsa.pub ``` #### 2. 将公钥复制到远程主机 ```bash ssh-copy-id -i ~/.ssh/id_rsa.pub abc@远程主机IP ``` #### 3. 脚本中直接使用SSH ```bash #!/bin/bash ssh abc@远程主机IP "要执行的命令" # 无需密码 ``` --- ### 五、注意事项 1. **命令中的特殊字符**: - 如果命令包含 `$`, `"`, `'` 等符号,需用转义或引号包裹,例如: ```bash sshpass -p "密码" ssh abc@主机 "echo \$HOME && touch /tmp/file" ``` 2. **调试技巧**: - 添加 `-v` 参数输出详细日志: ```bash sshpass -p "密码" ssh -v abc@主机 "命令" ``` 如需进一步优化或解决特定问题,请提供更多使用场景细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值