使用 ssh 循环运行 bash

使用 ssh 循环运行 bash

我有一个连接到家庭网络的树莓派,但每次重新启动时,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即可。其他一些可能有帮助的选项是:

  1. 获取网络上的活动 IP 列表

     nmap -sP 192.168.0.*
    
  2. 使用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 发行版上。

github 上的 Masscan

答案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

可能

相关内容