示例:使用 Op 脚本自定义 show interfaces terse 命令的输出
此示例使用 操作脚本 自定义命令的 show interfaces terse
输出。提供了 XSLT 脚本的逐行说明。
要求
此示例使用运行 Junos OS 的设备。
概述和操作脚本
默认情况下,命令的 show interfaces terse
布局如下所示:
user@host> show interfaces terse Interface Admin Link Proto Local Remote dsc up up fxp0 up up fxp0.0 up up inet 192.168.71.246/21 fxp1 up up fxp1.0 up up inet 10.0.0.4/8 inet6 fe80::200:ff:fe00:4/64 fc00::10:0:0:4/64 tnp 4 gre up up ipip up up lo0 up up lo0.0 up up inet 127.0.0.1 --> 0/0 lo0.16385 up up inet inet6 fe80::2a0:a5ff:fe12:2f04 lsi up up mtun up up pimd up up pime up up tap up up
在 Junos XML 中,输出字段表示如下:
user@host> show interfaces terse | display xml <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.0R1/junos"> <interface-information xmlns="http://xml.juniper.net/junos/10.0R1/junos-interface" junos:style="terse"> <physical-interface> <name>dsc</name> <admin-status>up</admin-status> <oper-status>up</oper-status> </physical-interface> <physical-interface> <name>fxp0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> <logical-interface> <name>fxp0.0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> ... Remainder of output omitted for brevity ...
XSLT 语法
以下脚本自定义命令的 show interfaces terse
输出。提供了脚本的逐行说明。
1 <?xml version="1.0" standalone="yes"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:junos="http://xml.juniper.net/junos/*/junos" 5 xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" 6 xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0"> 7 <xsl:import href="../import/junos.xsl"/> 8 <xsl:variable name="arguments"> 9 <argument> 10 <name>interface</name> 11 <description>Name of interface to display</description> 12 </argument> 13 <argument> 14 <name>protocol</name> 15 <description>Protocol to display (inet, inet6)</description> 16 </argument> 17 </xsl:variable> 18 <xsl:param name="interface"/> 19 <xsl:param name="protocol"/> 20 <xsl:template match="/"> 21 <op-script-results> 22 <xsl:variable name="rpc"> 23 <get-interface-information> 24 <terse/> 25 <xsl:if test="$interface"> 26 <interface-name> 27 <xsl:value-of select="$interface"/> 28 </interface-name> 29 </xsl:if> 30 </get-interface-information> 31 </xsl:variable> 32 <xsl:variable name="out" select="jcs:invoke($rpc)"/> 33 <interface-information junos:style="terse"> 34 <xsl:choose> 35 <xsl:when test="$protocol='inet' or $protocol='inet6' or $protocol='mpls' or $protocol='tnp'"> 36 <xsl:for-each select="$out/physical-interface/ logical-interface[address-family/address-family-name = $protocol]"> 37 <xsl:call-template name="intf"/> 38 </xsl:for-each> 39 </xsl:when> 40 <xsl:when test="$protocol"> 41 <xnm:error> 42 <message> 43 <xsl:text>invalid protocol: </xsl:text> 44 <xsl:value-of select="$protocol"/> 45 </message> 46 </xnm:error> 47 </xsl:when> 48 <xsl:otherwise> 49 <xsl:for-each select="$out/physical-interface/logical-interface"> 50 <xsl:call-template name="intf"/> 51 </xsl:for-each> 52 </xsl:otherwise> 53 </xsl:choose> 54 </interface-information> 55 </op-script-results> 56 </xsl:template> 57 <xsl:template name="intf"> 58 <xsl:variable name="status"> 59 <xsl:choose> 60 <xsl:when test="admin-status='up' and oper-status='up'"> 61 <xsl:text> </xsl:text> 62 </xsl:when> 63 <xsl:when test="admin-status='down'"> 64 <xsl:text>offline</xsl:text> 65 </xsl:when> 66 <xsl:when test="oper-status='down' and ../admin-status='down'"> 67 <xsl:text>p-offline</xsl:text> 68 </xsl:when> 69 <xsl:when test="oper-status='down' and ../oper-status='down'"> 70 <xsl:text>p-down</xsl:text> 71 </xsl:when> 72 <xsl:when test="oper-status='down'"> 73 <xsl:text>down</xsl:text> 74 </xsl:when> 75 <xsl:otherwise> 76 <xsl:value-of select="concat(oper-status, '/', admin-status)"/> 77 </xsl:otherwise> 78 </xsl:choose> 79 </xsl:variable> 80 <xsl:variable name="desc"> 81 <xsl:choose> 82 <xsl:when test="description"> 83 <xsl:value-of select="description"/> 84 </xsl:when> 85 <xsl:when test="../description"> 86 <xsl:value-of select="../description"/> 87 </xsl:when> 88 </xsl:choose> 89 </xsl:variable> 90 <logical-interface> 91 <name><xsl:value-of select="name"/></name> 92 <xsl:if test="string-length($desc)"> 93 <admin-status><xsl:value-of select="$desc"/></admin-status> 94 </xsl:if> 95 <admin-status><xsl:value-of select="$status"/></admin-status> 96 <xsl:choose> 97 <xsl:when test="$protocol"> 98 <xsl:copy-of select="address-family[address-family-name = $protocol]"/> 99 </xsl:when> 100 <xsl:otherwise> 101 <xsl:copy-of select="address-family"/> 102 </xsl:otherwise> 103 </xsl:choose> 104 </logical-interface> 105 </xsl:template> 106 </xsl:stylesheet>
逐行讲解
第 1 行至第 7 行、第 20 行以及第 105 行和第 106 行是您在每个操作脚本中都包含的样板。有关更多信息,请参阅 Op Scripts 所需的样板。
1 <?xml version="1.0" standalone="yes"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:junos="http://xml.juniper.net/junos/*/junos" 5 xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" 6 xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0"> 7 <xsl:import href="../import/junos.xsl"/> ... 20 <xsl:template match="/"> ... 105 </xsl:template> 106 </xsl:stylesheet>
第 8 行至第 17 行声明称为的 arguments
变量,其中包含脚本的两个参数: interface
和 protocol
。此可变声明将引起 interface
并在 protocol
命令行界面 (CLI) 中显示为脚本可用参数。
8 <xsl:variable name="arguments"> 9 <argument> 10 <name>interface</name> 11 <description>Name of interface to display</description> 12 </argument> 13 <argument> 14 <name>protocol</name> 15 <description>Protocol to display (inet, inet6)</description> 16 </argument> 17 </xsl:variable>
第 18 行和第 19 行声明脚本的两个参数,对应于在第 8 行到 17 行中创建的参数。参数名称必须与参数名称完全匹配。
18 <xsl:param name="interface"/> 19 <xsl:param name="protocol"/>
第 20 行至第 31 行声明名为 rpc
的变量。命令 show interfaces terse
分配给 rpc
变量。如果在 interface
执行脚本时包含该参数,则该参数的值(接口名称)将传递到脚本中。
20 <xsl:template match="/"> 21 <op-script-results> 22 <xsl:variable name="rpc"> 23 <get-interface-information> 24 <terse/> 25 <xsl:if test="$interface"> 26 <interface-name> 27 <xsl:value-of select="$interface"/> 28 </interface-name> 29 </xsl:if> 30 </get-interface-information> 31 </xsl:variable>
第 32 行声明名为 out
的变量,并适用于 rpc
执行变量 (show interfaces terse
命令)。
32 <xsl:variable name="out" select="jcs:invoke($rpc)"/>
第 33 行指定正在修改的命令的show interfaces
输出级别为terse
(相对extensive
detail
于 , 等)。
33 <interface-information junos:style="terse">
第 34 行至第 39 行指定,如果在执行脚本时包含protocol
该参数,并且您指定的协议值是 inet
、 inet6
mpls
或 tnp
, intf
该模板将应用于输出中协议类型的每个实例。
34 <xsl:choose> 35 <xsl:when test="$protocol='inet' or $protocol='inet6' or $protocol='mpls' or $protocol='tnp'"> 36 <xsl:for-each select="$out/physical-interface/ logical-interface[address-family/address-family-name = $protocol]"> 37 <xsl:call-template name="intf"/> 38 </xsl:for-each> 39 </xsl:when>
第 40 行至第 47 行指定,如果在执行脚本时包含protocol
该参数,并且您指定的协议值是生成错误消息以外的mpls
inet
inet6
tnp
其他内容,
40 <xsl:when test="$protocol"> 41 <xnm:error> 42 <message> 43 <xsl:text>invalid protocol: </xsl:text> 44 <xsl:value-of select="$protocol"/> 45 </message> 46 </xnm:error> 47 </xsl:when>
第 48 行到 52 行指定,如果执行脚本时未包含 protocol
该参数, intf
则该模板将应用于输出中的每个逻辑接口。
48 <xsl:otherwise> 49 <xsl:for-each select="$out/physical-interface/logical-interface"> 50 <xsl:call-template name="intf"/> 51 </xsl:for-each> 52 </xsl:otherwise>
第 53 行到 56 行是关闭标记。
53 </xsl:choose> 54 </interface-information> 55 </op-script-results> 56 </xsl:template>
第 57 行打开 intf
了模板。此模板可自定义命令的 show interfaces terse
输出。
57 <xsl:template name="intf">
第 58 行声明称为的 status
变量,其目的是指定如何报告接口状态。第 59 行到 78 行包含一个 <xsl:choose>
说明,该指令通过考虑所有可能的状态来填充 status
变量。一如既往地在 XSLT 中执行评估为 TRUE 的第一个 <xsl:when>
指令,其余部分将忽略。每个说明都 <xsl:when>
单独解释。
58 <xsl:variable name="status"> 59 <xsl:choose>
第 60 行至第 62 行指定,如果 admin-status
已“打开”且 oper-status
“已启动”,则不会生成输出。在这种情况下, status
变量仍然为空。
60 <xsl:when test="admin-status='up' and oper-status='up'"> 61 <xsl:text> </xsl:text> 62 </xsl:when>
第 63 行至第 65 行指定如果 admin-status
为“停机”, status
则变量包含文本 offline
。
63 <xsl:when test="admin-status='down'"> 64 <xsl:text>offline</xsl:text> 65 </xsl:when>
第 66 行至第 68 行指定如果 oper-status
为“停机”且物理接口 admin-status
为“停机”, status
则变量包含文本 p-offline
。(../
选择物理接口。)
66 <xsl:when test="oper-status='down' and ../admin-status='down'"> 67 <xsl:text>p-offline</xsl:text> 68 </xsl:when>
第 69 行至第 71 行指定如果 oper-status
为“停机”且物理接口 oper-status
为“停机”, status
则变量包含文本 p-down
。(../
选择物理接口。)
69 <xsl:when test="oper-status='down' and ../oper-status='down'"> 70 <xsl:text>p-down</xsl:text> 71 </xsl:when>
第 72 行至第 74 行指定如果 oper-status
为“停机”, status
则变量包含文本 down
。
72 <xsl:when test="oper-status='down'"> 73 <xsl:text>down</xsl:text> 74 </xsl:when>
第 75 行至第 77 行指定,如果没有测试案例属实, status
则变量包含 oper-status
且 admin-status
与斜线串联,作为分隔器。
75 <xsl:otherwise> 76 <xsl:value-of select="concat(oper-status, '/', admin-status)"/> 77 </xsl:otherwise>
第 78 行和第 79 行是关闭标记。
78 </xsl:choose> 79 </xsl:variable>
第 80 行到 89 行定义一个称为的 desc
变量。该 <xsl:choose>
说明通过选择可用的最特定接口说明来填充变量。如果配置中包含逻辑接口说明,则用于填充 desc
变量。如果未使用,则使用物理接口说明。如果配置中未包含物理接口说明,则变量仍为空。一如既往地在 XSLT 中执行评估为 TRUE 的第一个 <xsl:when>
指令,其余部分将忽略。
80 <xsl:variable name="desc"> 81 <xsl:choose> 82 <xsl:when test="description"> 83 <xsl:value-of select="description"/> 84 </xsl:when> 85 <xsl:when test="../description"> 86 <xsl:value-of select="../description"/> 87 </xsl:when> 88 </xsl:choose> 89 </xsl:variable>
脚本的其余部分指定了操作模式输出的显示方式。
第 90 行和第 91 行指定在输出中首先显示逻辑接口名称。
90 <logical-interface> 91 <name><xsl:value-of select="name"/></name>
第 92 行到 94 行测试变量是否 desc
具有非零数字符。如果字符数超过零,则接口说明显示在字段的标准位置 admin-status
中。(在标准输出中 admin-status
,字段显示在第二行。)
92 <xsl:if test="string-length($desc)"> 93 <admin-status><xsl:value-of select="$desc"/></admin-status> 94 </xsl:if>
第 95 行指定下一个变量中定义的 status
接口状态显示。
95 <admin-status><xsl:value-of select="$status"/></admin-status>
第 96 行到 103 行指定,如果在执行脚本时包含 protocol
该参数,将仅显示与配置的协议的接口。如果未包含该 protocol
参数,将显示所有接口。
96 <xsl:choose> 97 <xsl:when test="$protocol"> 98 <xsl:copy-of select="address-family[address-family-name = $protocol]"/> 99 </xsl:when> 100 <xsl:otherwise> 101 <xsl:copy-of select="address-family"/> 102 </xsl:otherwise> 103 </xsl:choose>
第 104 行到 106 行是关闭标记。
104 </logical-interface> 105 </xsl:template> 106 </xsl:stylesheet>
SLAX 语法
脚本的 SLAX 版本如下:
version 1.0; ns junos = "http://xml.juniper.net/junos/*/junos"; ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; import "../import/junos.xsl"; var $arguments = { <argument> { <name> "interface"; <description> "Name of interface to display"; } <argument> { <name> "protocol"; <description> "Protocol to display (inet, inet6)"; } } param $interface; param $protocol; match / { <op-script-results> { var $rpc = { <get-interface-information> { <terse>; if ($interface) { <interface-name> $interface; } } } var $out = jcs:invoke($rpc); <interface-information junos:style="terse"> { if ($protocol='inet' or $protocol='inet6' or $protocol='mpls' or $protocol='tnp') { for-each ($out/physical-interface/ logical-interface[address-family/address-family-name = $protocol]) { call intf(); } } else if ($protocol) { <xnm:error> { <message> { expr "invalid protocol: "; expr $protocol; } } } else { for-each ($out/physical-interface/logical-interface) { call intf(); } } } } } intf () { var $status = { if (admin-status='up' and oper-status='up') { } else if (admin-status='down') { expr "offline"; } else if (oper-status='down' and ../admin-status='down') { expr "p-offline"; } else if (oper-status='down' and ../oper-status='down') { expr "p-down"; } else if (oper-status='down') { expr "down"; } else { expr oper-status _ '/' _ admin-status; } } var $desc = { if (description) { expr description; } else if (../description) { expr ../description; } } <logical-interface> { <name> name; if (string-length($desc)) { <admin-status> $desc; } <admin-status> $status; if ($protocol) { copy-of address-family[address-family-name = $protocol]; } else { copy-of address-family; } } }
配置
程序
逐步过程
要下载、启用和测试脚本:
将 XSLT 或 SLAX 脚本复制到文本文件中,指定文件 接口.xsl 或 interface.slax ,并将其复制到设备上的 /var/db/scripts/op/ 目录。
在配置模式下
[edit system scripts op]
,在file
层次结构级别和接口.xsl 或接口.slax 上相应包含语句。[edit system scripts op] user@host# set file interface.(slax | xsl)
commit and-quit
发出 命令提交配置并返回到操作模式。[edit] user@host# commit and-quit
执行操作脚本,方法是
op interface
发出操作模式命令。
验证
验证提交脚本输出
目的
验证脚本是否按预期运行。
行动
show interfaces terse
发出和op interface
操作命令并比较输出。命令show interfaces terse
显示标准输出。命令op interface
显示自定义输出。
user@host> show interfaces terse Interface Admin Link Proto Local Remote dsc up up fxp0 up up fxp0.0 up up inet 192.168.71.246/21 fxp1 up up fxp1.0 up up inet 10.0.0.4/8 inet6 fe80::200:ff:fe00:4/64 fc00::10:0:0:4/64 tnp 4 gre up up ipip up up lo0 up up lo0.0 up up inet 127.0.0.1 --> 0/0 lo0.16385 up up inet inet6 fe80::2a0:a5ff:fe12:2f04 lsi up up mtun up up pimd up up pime up up tap up up user@host> op interface Interface Admin Link Proto Local Remote fxp0.0 This is the Ethernet Management interface. inet 192.168.71.246/21 fxp1.0 inet 10.0.0.4/8 inet6 fe80::200:ff:fe00:4/64 fc00::10:0:0:4/64 tnp 4 lo0.0 inet 127.0.0.1 --> 0/0 lo0.16385 inet inet6 fe80::2a0:a5ff:fe12:2f04-->
op interface
发出不同层次结构级别的操作命令并查看输出。例如:
user@host> op interface interface fxp0 Interface Admin Link Proto Local Remote fxp0.0 This is the Ethernet Management interface. inet 192.168.71.246/21 user@host> op interface protocol inet Interface Admin Link Proto Local Remote fxp0.0 This is the Ethernet Management interface. inet 192.168.71.246/21 fxp1.0 inet 10.0.0.4/8 lo0.0 inet 127.0.0.1 --> 0/0 lo0.16385 inet