我有一个 CSV 文件,其中包含如下条目:
ipaddress,VLAN,VLANid
10.192.168.1,vlan-xyz,3
10.192.168.1,vlan-abc,8
10.192.168.1,vlan-mnp,11
10.192.163.24,vlan-llz,3
10.192.163.24,vlan-bbz,5
10.192.163.24,vlan-xggz,23
等等,我需要在远程思科交换机上执行一些思科命令,例如:
现在如果我做这样的事情
while read ipaddress vlan vlanid
ssh user@ipaddress << 'ENDSSH'
int VLAN vlan-xyz
switchport access vlan vlanid
wr
ENDSSH
done < inputfile
它每次都会进行 ssh 并提示我输入文件中每一行的密码,即使对于相同的 ip 地址也是如此。有什么办法可以克服这个问题吗?我正在考虑将文件中的另外两列放入一个数组中,就像单个 ip 地址一样:
eg for IP:10.192.168.1
array="
int VLAN vlan-xyz
switchport access vlan 3
wr
int VLAN vlan-abc
switchport access vlan 8
"
for next ip ......
等等
我该如何做到这一点,以便我可以像这样传递一个 ip 的命令数组:
while read ipaddress
ssh user@ipaddress " $array"
done < inputfile
但我仍然需要确保,如果我在 while 循环中获得类似的 ip 地址,则不应 ssh 进入它,而仅当它找到新的 ip 地址时。
我在用空的使用 ssh 以非交互方式将密码传递到远程交换机,但它也不是很好,因为如果远程命令失败,它不会出现任何错误。包括密码在内的所有内容都会记录到其日志文件中。
注意:所有 ip 的用户密码都相同
答案1
以下这些功能是一个好的开始。foo
将读取 CSV 文件的内容,并填充 IP 地址数组,该数组将在每次迭代时进行检查,以便ssh
不会使用同一 IP 多次执行。
# Usage: inarray "$value" "${array[@]}"
inarray()
{
local n=$1 h; shift
for h; do
[[ $n = "$h" ]] && return
done
return 1
}
# Usage: foo "$csv_file_name"
foo()
{
local ips=() arr=() filename="$1"
{ read; while IFS= read -r line; do
IFS=, read -ra arr <<< "$line"
if ! inarray "${arr[0]}" "${ips[@]}"; then
# Do whatever you want with "${arr[@]}"
# Example for arr:
# arr[0]=10.192.168.1, arr[1]=vlan-xyz, arr[2]=3
ips+=("${arr[0]}")
fi
done; } < "$filename"
}
答案2
听起来像是 Perl 的工作:
#!/usr/bin/perl
use strict;
use warnings;
my $input_file=shift//die "No input file name given.\n";
open my $if,'<',$input_file or die "Couldn't open $input_file: $!\n";
my %ip_data;
<$if>; # Throw away the header
while(<$if>){
my ($ip,$vlan,$vlan_id)=split /\s*,\s*/;
push $ip_data{$ip}, <<EOI;
int VLAN $vlan
switchport access vlan $vlan_id
wr
EOI
}
close $if;
for my $ip (sort keys %ip_data){ #Fork-exec an SSH process for each IP address:
my $pid = fork;
$pid ? () : exec "ssh user@$ip \"$ip_data{$ip}\"";
}
将此脚本保存到文件中,使其可执行 ( chmod +x script_file
) 并像这样调用它:
$ ./script_file inputfile
两条评论: