![使用 ssh 循环运行 bash](https://linux22.com/image/187248/%E4%BD%BF%E7%94%A8%20ssh%20%E5%BE%AA%E7%8E%AF%E8%BF%90%E8%A1%8C%20bash.png)
我有一个连接到家庭网络的树莓派,但每次重新启动时,IP 地址都会发生变化。我不想每次都调用 ssh user@ipaddress,而是想运行 bash 脚本来了解哪个地址有效。
我尝试运行ssh user@ipaddress
几次来更改 IP 地址的最后一个数字。我不知道 bash 是如何工作的,所以我尝试创建一个文件.sh
来做到这一点:
for i in {1..100}
do
call=`ssh [email protected].$i`
if [['$call'==*'user'*]]; then
echo "$i"
else
:
fi
done
我的问题是:
- 我不打印任何东西
- 它卡在第一次调用中并且没有循环
所以我想知道当它是另一个设备时是否有 bash 函数来传递命令,因为我知道我的用户名,我只需要在第一行的命令输出中找到我的用户名,而不是'无需等待更多输出。
答案1
执行此操作的正确方法® 是将 Pi 设置为具有静态 IP,以便它在重新启动时不会更改,或者设置本地 DNS 服务器来解析主机名。设置静态 IP 是迄今为止最简单的。只要搜索“raspbian static IP”就可以找到几十个教程。这是一个:https://thepihut.com/blogs/raspberry-pi-tutorials/how-to-give-your-raspberry-pi-a-static-ip-address-update
现在,您的脚本由于多种原因而无法运行。首先,这永远行不通:
call=`ssh [email protected].$i`
如果机器不允许您进入或无法访问,那么它将打印错误,但该错误被打印到标准错误,而不是标准输出,因此$call
将为空。如果它确实有效并且您通过 ssh 进入机器,那么您将登录,并且再次$call
为空,因为没有返回任何内容。
无论如何,你的if
都是语法错误。这:
if [['$call'==*'user'*]]; then
应该是这样的:
if [[ "$call" == *user* ]]; then
[[
和之前和之前需要空格]]
,如果将变量放在单引号 ( '$call'
) 中,则该变量不会扩展:
$ echo '$call'
$call
您可能想要做的是尝试登录,运行命令,如果运行则存储 ip。像这样的东西:
#!/bin/bash
for i in {1..100}
do
## try to run a command and, if it works, we know the ip.
## you can use the command 'true' for this
if ssh [email protected].$i true; then
echo "The IP is 192.168.0.1.$i"
break
fi
done
然而,这确实非常低效且缓慢。不要这样做。只需设置一个静态IP即可。其他一些可能有帮助的选项是:
获取网络上的活动 IP 列表
nmap -sP 192.168.0.*
使用
ping
而不是ssh
查看哪台机器正在运行:for i in {1..100} do if ping -c1 192.168.0.$i 2>/dev/null; then echo "The first IP that is UP is 192.168.0.1.$i" break fi done
但实际上,如果您需要设置静态 IP 的帮助,请发布一个有关该问题的新问题。这并不是解决您问题的好方法。
答案2
使用mDNS
(avahi) 发现 IP 地址。远程必须至少运行服务器并进行配置,本地必须至少有客户端。它是一种分布式(比普通的)本地 DNS。您还可以尝试让路由器的 DHCP 分配静态 IP 地址。
答案3
要快速连接,请使用端口masscan
扫描活动主机ssh
:
sudo masscan 192.168.0.1/24 --ports 22 --rate 100000 > alive
awk '{print $6}' alive > file
while read -r line; do ssh user@"$line"; done < file
更好,按照建议的一句台词@特登:
ssh user@$(sudo masscan 192.168.0.1/24 --ports 22 --rate 100000 | awk '{print $6}')
masscan
被打包在一些 Linux 发行版上。
答案4
在 Pi 上设置一个返回“This is the Pi of iam_agf”的网络服务器。或者甚至是返回 IP 的动态页面,例如“192.168.0.15 iam_agf”。这是为了确保这是您的设备,而不是打印机或咖啡机。
您可以使用 nmap 查看哪些 IP 正在运行网络服务器,然后检查这些 IP 是否包含您的关键字和 IP。
获得 IP 后,将其放入 /etc/hosts 文件中,这样您就可以通过名称轻松访问 pi。
简单检查它是否可以在没有 nmap 的情况下工作,可能需要一些时间:
for i in $(seq 1 254); do
curl "http://192.168.0.${i}" | grep iam_igf
done
nmap 有一个名为 ssh-brute 的插件,您可以使用一个固定的用户名和密码组合来尝试此操作。https://nmap.org/nsedoc/scripts/ssh-brute.html
还有您最初可能正在寻找的内容:
#this will open an ssh connection and wait for you to type stuff:
ssh user@IP
#this will run a command after the connection is open, then close it
ssh user@IP command
# example
ssh user@IP echo ok
# or just use the true command to avoid output
ssh user@IP true
# so this loop might do what you need, (untested, make backups of /etc/hosts first!)
for i in $(seq 1 254); do
if ssh "[email protected].${i}" true;
then
sed -i "/[0-9.]* mypi/d" /etc/hosts
echo "192.168.0.${i} mypi" >> /etc/hosts
break
fi
done
可能