我花了一些时间试图通过各种互联网搜索和挖掘stackoverflow来解决这个问题。我会尽力解释这个最好的菜鸟。
我有一个脚本,用于搜索配置存储库目录,该目录中填充了我们已部署的每个Juniper和Cisco路由器和交换机的目录。每个设备目录都有一两个我感兴趣的文件,“show.version”和“show.chassis.hardware”,除非它们没有。第二个文件“show.chassis.hardware”不是Cisco盒子所具有的命令,因此Cisco设备目录中不存在该文件。还有一个命名方案可以很容易地告诉我该设备是Juniper还是Cisco,这也是我的脚本存在的部分原因。
为了让事情变得更有趣,不同的模型甚至软件版本以不同的格式输出show.version文件(对于Cisco和Juniper),所以我的awk充满了我们将遇到的所有不同领域。
脚本:
#!/usr/local/bin/zsh
svn="$HOME/svn/nw_config_data/"
case "$1" in
("-a")
hosts=""
;;
("-b")
hosts=".bb.domain.net"
;;
("-c")
hosts=".cpe.domain.net"
;;
("-e")
hosts=".etech.domain.net"
;;
("-k")
hosts=".core.domain.net"
;;
("-m")
hosts=".maint.domain.net"
;;
("-o")
hosts=".ohgov.domain.net"
;;
esac
dirs=($(ls -d $svn*$hosts*))
for hostdir in $dirs
do host=$(echo $hostdir | grep -Eo "(\w|\.|-)*$")
awk -v h=$host '/^Model/{m=$2} /^Model number/{m=$4} /^\*0/{m=$2}
/^JUNOS Base OS boot/{v=$5} /^Junos:/{v="["$2"]"} /^BOOTLDR:/{v=$7}
/^JUNOS EX Software Suite/{v=$5} /^ROM:/{v=$5} /^JUNOS Software
Release/{v=$4} /^Chassis/{s=$2} /^Motherboard serial number/{s=$3}
END {if(m!="number") {printf("%s %s %s %s\n",h,m,v,s)}}'
"$hostdir/show.version" "$hostdir/show.chassis.hardware"
done
运行脚本时的样子:
% cver -b
device1-e0.bb.domain.net ex4300-24t [14.1X53-D25.2] Serial#
device2-e0.bb.domain.net ex4300-24t [14.1X53-D25.2] Serial#
awk: can't open file /home/clmbn eng2/a/rwalker/svn/nw_config_data/device3-e1.bb.domain.net/show.chassis.hardware
input record number 55, file /home/clmbn-eng2/a/rwalker/svn/nw_config_data/device3-e1.bb.domain.net/show.chassis.hardware
source line number 1
device4-r0.bb.domain.net m7i [13.3R6.5] Serial#
...
我希望它看起来像什么
% cver -b
device1-e0.bb.domain.net ex4300-24t [14.1X53-D25.2] Serial#
device2-e0.bb.domain.net ex4300-24t [14.1X53-D25.2] Serial#
device3-e1.bb.domain.net C3750 12.1(14r)EA1a, Serial#
device4-r0.bb.domain.net m7i [13.3R6.5] Serial#
...
我有13个目录没有“show.chassis.hardware”文件,但确实有“show.version”文件,它确实包含了我需要的所有信息。我有一个没有文件的目录,但没关系,因为该设备将被替换。
从我读过的内容来看,awk可能无法做到这一点,但我相信那里有人知道如何让它发挥作用。如果我的方法(shell和awk脚本)不能正常工作而我需要用别的东西(例如Perl或Python)来完成,我将完全陷入困境,直到我能够学到足够的东西来将我的脚本转换为其中一种语言。
此外,我们没有在此服务器上安装bash,因为我不是管理员,所以我不知道什么时候会这样做。
答案 0 :(得分:2)
你需要
-f file
如果文件存在且为常规文件,则为true。
if [[ -f "$hostdir/show.version" && -f "$hostdir/show.chassis.hardware" ]]; then
# your awk command goes here...
awk '{ }' "$hostdir/show.version" "$hostdir/show.chassis.hardware"
else
echo "not enough files found"
fi
您可以参考:http://zsh.sourceforge.net/Doc/Release/Conditional-Expressions.html
- 编辑 -
这个脚本跳过没有的目录很酷 有文件,但它不会从中提取信息 无论如何,“show.version”文件并打印该信息。所以输出 显示device1,device2,device 4 ...
以下是代码段
function myfunc(){
# replace with your awk
awk '{ print }' "$@"
}
if [[ -f "$hostdir/show.version" && -f "$hostdir/show.chassis.hardware" ]]; then
# your awk command goes here...
myfunc "$hostdir/show.version" "$hostdir/show.chassis.hardware"
else
echo "not enough files found"
# pass only one file, version file
myfunc "$hostdir/show.version"
fi
答案 1 :(得分:1)
你可以使用zsh' (...|...)
globbing:
$ mkdir foo bar; touch {foo,bar}/show.version foo/show.chassis.hardware
$ echo foo/show.(version|chassis.hardware)
foo/show.chassis.hardware foo/show.version
$ echo bar/show.(version|chassis.hardware)
bar/show.version
由于这是通配的,它只会扩展到现有文件。所以你的awk命令看起来像:
awk -v h=$host '/^Model/{m=$2} ... END {...}' "$hostdir"/show.(version|chassis.hardware)
(省略awk脚本以提高可读性)
我还使用关联数组而不是案例来简化你的脚本:
#!/usr/local/bin/zsh
usage () {
echo "Help!" # echo your help message here
exit $1
}
svn="$HOME/svn/nw_config_data/"
declare -A hosts # make associative array
hosts["-a"]=""
hosts["-b"]=".bb.domain.net"
hosts["-c"]=".cpe.domain.net"
hosts["-e"]=".etech.domain.net"
hosts["-k"]=".core.domain.net"
hosts["-m"]=".maint.domain.net"
hosts["-o"]=".ohgov.domain.net"
if [[ $1 == -h ]]
then
usage
elif (( ${+hosts["$1"]} )) # check if $1 is a key in hosts
then
echo "Invalid option: $1"
usage 1 # exit with status 1 to indicate error
fi
dirs=( $svn*$hosts["$1"]* ) # no need for ls here
for hostdir in $dirs
do
host=$(echo $hostdir | grep -Eo "(\w|\.|-)*$")
awk -v h=$host '
/^Model/{m=$2}
/^Model number/{m=$4}
/^\*0/{m=$2}
/^JUNOS Base OS boot/{v=$5}
/^Junos:/{v="["$2"]"}
/^BOOTLDR:/{v=$7}
/^JUNOS EX Software Suite/{v=$5}
/^ROM:/{v=$5}
/^JUNOS Software Release/{v=$4}
/^Chassis/{s=$2}
/^Motherboard serial number/{s=$3}
END {if(m!="number") {printf("%s %s %s %s\n",h,m,v,s)}}' \
"$hostdir"/show.(version|chassis.hardware)
done
或者,您可以对数组使用简洁的case
:
declare -A hosts # make associative array
hosts["-a"]=""
hosts["-b"]=".bb.domain.net"
hosts["-c"]=".cpe.domain.net"
hosts["-e"]=".etech.domain.net"
hosts["-k"]=".core.domain.net"
hosts["-m"]=".maint.domain.net"
hosts["-o"]=".ohgov.domain.net"
case $1 in
-[abcekmno]) dirs=( $svn*${hosts["$1"]}* )
;;
-h|help) usage
;;
*) echo "Invalid option: $1"
usage 1 # exit with status 1 to indicate error
;;
esac