我正在尝试通过 ssh 在一系列服务器上运行命令。我最近更改了 ssh 端口以避免互联网扫描仪,但这破坏了我的脚本。有谁知道在 for 循环中为每个 user@server 条目指定不同端口的“简单方法”?
for i in '[email protected] -p 12345' '[email protected] -p 54321'
do printf "\e[%sm%s\e[00m\n" 32 $i
ssh $i crontab -l
done
第二行只是在输出之前打印服务器名称(为了可读性)。
它给我的不是幸福,而是:ssh: Could not resolve hostname server1.domain1.com -p 12345: Name or service not known
以前,当所有端口都是默认的 22 并且不需要指定时,它就可以工作。
OpenSSH 的最新版本
ssh
(自 v7.7 起)(及其scp
和sftp
)将接受 URI 形式的目标。如果您愿意,可以将端口号指定为 URI 的一部分,例如“ssh://someuser@somehost:42”连接到端口 42。就 shell 而言,URI 的优点是它是单个字符串被关注到。所以你可以这样做:SSH URI 的一般形式是“ssh://user@host:port”。“用户”和“端口”部分都是可选的,如果您不需要为其指定值,则可以省略它们(以及“@”或“:”标点符号)。
正确的方法是将其存储在配置中,而不是在每个连接上指定所有内容。
在
~/.ssh/config
你可以有:然后
ssh server1.domain1.com
就会ssh serv2
做正确的事™ 无需记住每台计算机使用的用户名或端口。对脚本和人类都有好处。如果您稍后更改端口,则可以在一个位置进行修改。
还可以使用通配符,因此如果所有计算机的
domain1.com
sshd 都在端口 1234 上侦听,您可以将它们全部与 匹配Host *.domain1.com
,而不必单独列出它们。对于
for
可以循环多个变量的循环,请切换到zsh
. 您已经zsh
通过不引用变量来使用语法:要循环参数列表,您可以使用具有多维数组的 shell,例如
ksh93
:或者将包含字符串的数组元素与参数使用您知道字符串中不会出现的字符连接起来,然后将它们分开。
zsh
确实具有${(s[x])var}
分裂特征。ksh 和 bash 也可以,但只能通过笨重的 split+glob 来实现,当您忘记在那里引用扩展时,会隐式调用它。您可以将其用作:
这基本上就是您在方法中所做的,只是您使用空格而不是
:
分隔元素,但没有设置$IFS
也没有禁用全局。事实上,你
$i
没有被分割可以通过$IFS
设置为空字符串来解释,或者代码由 zsh 而不是 bash 运行,其中分割或通配符都不是在参数扩展时隐式完成的。在 zsh 中,如果您想要 IFS 分割,请使用,而
$=var
不是$var
,如果您想要通配:$~var
。bash 的$var
类似于 zsh 的$=~var
。所以在 zsh 中,你需要:一种可行的可移植方法
sh
是编写它:省略
-r
选项以read
允许值包含分隔符(此处为空格),方法是在它们前面加上反斜杠,如下所示:但与其他方法相反,它不允许这些值包含换行符(对于用户、主机、服务名称或端口号来说可能不是问题)。
另一种可移植的循环列表,所有列表都具有相同
$n
数量的元素,并且没有该限制,即将所有元素存储在位置参数中,并在循环中循环它们while [ "$#" -ge "$n" ]; do something with "$1" "$2"...; shift "$n"; done
。所以在这里:在 POSIX shell 中,循环遍历两个列表的通用解决方案,在循环的每次迭代中使用一对元素(任一列表中的一个):
多主机使用pdsh。广泛应用于拥有大量集群主机的数据中心。
从 pdsh 文档 ..
https://code.google.com/archive/p/pdsh/wikis/UsingPDSH.wiki
正如 Ángel 提到的,该工具与 ssh 配置文件一起使用。
下面的完整示例..
〜/ .ssh /配置
现在简单运行