我正在编写一个连接到使用 3 个不同用户的多个服务器的脚本。
#!/bin/ksh
server1=("abc1" "abc2")
server2=("abc3" "abc4")
server3=("abc5" "abc6")
for i in "${server1[@]}"
do ssh sam@$i "some command"
done
for i in "${server2[@]}"
do ssh danny@$i "some command"
done
for i in "${server3[@]}"
do ssh robert@$i "some command"
done
有没有一种方法可以将所有三个for
循环合并为一个。实际上我只想为多个连接编写一个 ssh 。
我尝试将所有服务器放在 1 个数组中,将用户放在另一个数组中
servers=("abc1" "abc2" "abc3" "abc4" "abc5" "abc6")
users=("sam" "Danny" "Robert")
for i in ${servers[@]}
do
ssh ${users[@]}@$i "some command"
done
但通过这种方式,脚本将每个用户放在每个服务器上,最终锁定服务帐户......
我想要的是一些循环所有服务器和用户的脚本,并且仅将用户Sam
与数组匹配、server1
用户与danny
数组匹配server2
以及用户robert
与数组匹配server3
。有没有更好的方法以干净、更好的方式将正确的用户与正确的服务器相匹配......
答案1
假设 Bash,正如标签所说(不是 shebang 所说的 ksh),我们可以使用名称引用使用给定整数标识符的相应数组变量:
users=(. userxyz user123 user221)
for n in 1 2 3
do
declare -n server=server$n
for i in "${server[@]}"
do ssh "${users[$n]}@$i" "some command"
done
done
使用合适的echo
,我们得到与原始脚本相同的输出:
ssh userxyz@abc1 some command
ssh userxyz@abc2 some command
ssh user123@abc3 some command
ssh user123@abc4 some command
ssh user221@abc5 some command
ssh user221@abc6 some command
要适应 Korn shell,您需要使用nameref
内置命令代替declare -n
。
更简单的方法可能只是一起考虑用户名/主机名:
servers=("userxyz@abc1" "userxyz@abc2"
"user123@abc3" "user123@abc4"
"user221@abc5" "user221@abc6")
for i in "${servers[@]}"
do ssh "$i" "some command"
done
答案2
如果user1
只与server1a
和相关联server1b
,与,等user2
相关联,则server2a
server2b
server2c
#!/bin/sh
set -- \
user1 server1a server1b -- \
user2 server2a server2b server2c -- \
user3 server3a --
while [ "$#" -ne 0 ]; do
user=$1; shift
until [ "$1" = -- ]; do
ssh "$user@$1" 'some command'
shift
done
# Shift off that "--" delimiter
shift
done
这使用位置参数来存储用户名和相应的服务器列表。由于它是单个字符串列表,因此我们将包含用户名和服务器名称的列表部分定界,--
以便我们可以轻松地看到何时需要新用户名或列表末尾。
外部循环遍历列表的各个部分,并将用户名分配给变量user
,而内部循环遍历服务器名称并调用,直到找到ssh
字符串。--
该脚本是为/bin/sh
和 编写的,因此也适用于ksh
和bash
。
鉴于上面的代码,ssh
将执行以下命令:
ssh user1@server1a 'some command'
ssh user1@server1b 'some command'
ssh user2@server2a 'some command'
ssh user2@server2b 'some command'
ssh user2@server2c 'some command'
ssh user3@server3a 'some command'
如果删除初始set
命令,您将能够像这样从命令行调用脚本,以获得相同的效果:
$ ./script user1 server1a server1b -- user2 server2a server2b server2c -- user3 server3a --
通过在内循环中进行额外的检查 ( ),您可以在命令行中|| [ "$#" -eq 0 ]
省略最后一个检查。--
如果您想做的是申请干燥原则并且仅从ssh
代码中的单个点调用,然后将该位提取到函数中。这是您的代码,经过修改以执行此操作:
#!/bin/ksh
server1=("abc1" "abc2")
server2=("abc3" "abc4")
server3=("abc5" "abc6")
process () {
ssh "$1@$2" 'some command'
}
for server in "${server1[@]}"; do
process sam "$server"
done
for server in "${server2[@]}"; do
process danny "$server"
done
for server in "${server3[@]}"; do
process robert "$server"
done