Rootop 服务器运维与web架构

while read line语句中ssh远程执行命令,只运行了一次。

while read line语句中ssh远程执行命令,只运行了一次。
目的:批量修改主机信息。

有一个host.txt文件,记录服务器ip,已经配置好秘钥登陆。如:

[root@m ~]# cat host.txt
192.168.10.71
192.168.10.72
192.168.10.73

现在想批量修改主机名,比如idc-001、idc-002 …,后面3位是数字
# 通过 expr 表达式实现shell中进行数学运算
# 通过 printf 格式化字符串,不足3位用0补全

# 先拼接出来主机名,再进一步添加修改功能

[root@m ~]# cat b
#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 n=`expr $n + 1`

done < host.txt

# 执行结果没问题

[root@m ~]# sh b
192.168.10.71 idc-001
192.168.10.72 idc-002
192.168.10.73 idc-003

# 下一步就要通过ssh登陆实现修改主机名

[root@m ~]# cat b
#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 ssh -o "StrictHostKeyChecking no" root@$ip "echo $hostname > /etc/hostname && hostname $hostname"
 n=`expr $n + 1`

done < host.txt

# 运行

[root@m ~]# sh b
192.168.10.71 idc-001
[root@m ~]# 

就执行了一行,退出了。去看71这台机器是修改成功了,但是72、73仍旧没变化。怀疑问题出在ssh上。

原因:
ssh中有个参数为 -n 通过man看到解释:

 
Redirects stdin from /dev/null (actually, prevents reading from stdin).  This must be used when ssh is run in the background.  A common trick is to
use this to run X11 programs on a remote machine.  For example, ssh -n shadows.cs.hut.fi emacs & will start an emacs on shadows.cs.hut.fi, and the
X11 connection will be automatically forwarded over an encrypted channel.  The ssh program will be put in the background.  (This does not work if
ssh needs to ask for a password or passphrase; see also the -f option.)

即ssh从stdin中读取了while read line的内容,导致while语句没有输入了,就执行完了。
-n的作用就是阻止ssh读取标准输入,为了验证这个结论,修改下host.txt文件,并且把ssh要执行的命令去掉。

[root@m ~]# cat b
#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 ssh -o "StrictHostKeyChecking no" root@$ip # 去掉了后面的命令
 n=`expr $n + 1`

done < host.txt
[root@m ~]# cat host.txt 最后两行为两条系统命令
192.168.10.71
uname -r
date

# 执行

[root@m ~]# sh b
192.168.10.71 idc-001
Pseudo-terminal will not be allocated because stdin is not a terminal.
3.10.0-514.el7.x86_64
Wed Apr 17 16:44:58 CST 2019

可以看到内核版本和日期,说明ssh从标准输入读取了内容做为命令执行了,导致while标准输入为空,最后退出。

# 修改后正确姿势,添加-n参数

#!/bin/bash
str="idc-"
n=1
while read ip
do

 host_num=`printf "%03d" $n`
 hostname=$str$host_num
 echo $ip $hostname
 ssh -n -o "StrictHostKeyChecking no" root@$ip "hostname $hostname && echo $hostname > /etc/hostname"
 n=`expr $n + 1`

done < host.txt

# 执行结果

[root@m ~]# sh b
192.168.10.71 idc-001
192.168.10.72 idc-002
192.168.10.73 idc-003

再去看72、73两台机器正确修改了。

原创文章,转载请注明。本文链接地址: https://www.rootop.org/pages/4311.html

作者:Venus

服务器运维与性能优化

评论已关闭。