Help us improve your experience.

Let us know what you think.

Do you have time for a two-minute survey?

Announcement: Try the Ask AI chatbot for answers to your technical questions about Juniper products and solutions.

close
header-navigation
keyboard_arrow_up
close
keyboard_arrow_left
Automation Scripting User Guide
Table of Contents Expand all
list Table of Contents
file_download PDF
{ "lLangCode": "en", "lName": "English", "lCountryCode": "us", "transcode": "en_US" }
English
keyboard_arrow_right

Example: Customize Output of the show interfaces terse Command Using an Op Script

date_range 15-Nov-23

This example uses an op script to customize the output of the show interfaces terse command. A line-by-line explanation of the XSLT script is provided.

Requirements

This example uses a device running Junos OS.

Overview and Op Script

By default, the layout of the show interfaces terse command looks like this:

content_copy zoom_out_map
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

In Junos XML, the output fields are represented as follows:

content_copy zoom_out_map
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 Syntax

The following script customizes the output of the show interfaces terse command. A line-by-line explanation of the script is provided.

content_copy zoom_out_map
   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>

Line-by-Line Explanation

Lines 1 through 7, Line 20, and Lines 105 and 106 are the boilerplate that you include in every op script. For more information, see Required Boilerplate for Op Scripts.

content_copy zoom_out_map
   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>

Lines 8 through 17 declare a variable called arguments, containing two arguments to the script: interface and protocol. This variable declaration causes interface and protocol to appear in the command-line interface (CLI) as available arguments to the script.

content_copy zoom_out_map
   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>

Lines 18 and 19 declare two parameters to the script, corresponding to the arguments created in Lines 8 through 17. The parameter names must exactly match the argument names.

content_copy zoom_out_map
  18        <xsl:param name="interface"/>
  19        <xsl:param name="protocol"/>

Lines 20 through 31 declare a variable named rpc. The show interfaces terse command is assigned to the rpc variable. If you include the interface argument when you execute the script, the value of the argument (the interface name) is passed into the script.

content_copy zoom_out_map
  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>

Line 32 declares a variable named out and applies to it the execution of the rpc variable (show interfaces terse command).

content_copy zoom_out_map
  32                <xsl:variable name="out" select="jcs:invoke($rpc)"/>

Line 33 specifies that the output level of the show interfaces command being modified is terse (as opposed to extensive, detail, and so on).

content_copy zoom_out_map
  33                <interface-information junos:style="terse">

Lines 34 through 39 specify that if you include the protocol argument when you execute the script and if the protocol value that you specify is inet, inet6, mpls, or tnp, the intf template is applied to each instance of that protocol type in the output.

content_copy zoom_out_map
  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>

Lines 40 through 47 specify that if you include the protocol argument when you execute the script and if the protocol value that you specify is something other than inet, inet6, mpls, or tnp, an error message is generated.

content_copy zoom_out_map
  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>

Lines 48 through 52 specify that if you do not include the protocol argument when you execute the script, the intf template is applied to each logical interface in the output.

content_copy zoom_out_map
  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>

Lines 53 through 56 are closing tags.

content_copy zoom_out_map
  53                    </xsl:choose>
  54                </interface-information>
  55            </op-script-results>
  56        </xsl:template>

Line 57 opens the intf template. This template customizes the output of the show interfaces terse command.

content_copy zoom_out_map
  57        <xsl:template name="intf">

Line 58 declares a variable called status, the purpose of which is to specify how the interface status is reported. Lines 59 through 78 contain a <xsl:choose> instruction that populates the status variable by considering all the possible states. As always in XSLT, the first <xsl:when> instruction that evaluates as TRUE is executed, and the remainder are ignored. Each <xsl:when> instruction is explained separately.

content_copy zoom_out_map
  58            <xsl:variable name="status">
  59                <xsl:choose>

Lines 60 through 62 specify that if admin-status is 'up' and oper-status is 'up', no output is generated. In this case, the status variable remains empty.

content_copy zoom_out_map
  60                    <xsl:when test="admin-status='up' and oper-status='up'">
  61                        <xsl:text> </xsl:text>
  62                    </xsl:when>

Lines 63 through 65 specify that if admin-status is 'down', the status variable contains the text offline.

content_copy zoom_out_map
  63                    <xsl:when test="admin-status='down'">
  64                        <xsl:text>offline</xsl:text>
  65                    </xsl:when>

Lines 66 through 68 specify that if oper-status is 'down' and the physical interface admin-status is 'down', the status variable contains the text p-offline. (../ selects the physical interface.)

content_copy zoom_out_map
  66                    <xsl:when test="oper-status='down' and ../admin-status='down'">
  67                        <xsl:text>p-offline</xsl:text>
  68                    </xsl:when>

Lines 69 through 71 specify that if oper-status is 'down' and the physical interface oper-status is 'down', the status variable contains the text p-down. (../ selects the physical interface.)

content_copy zoom_out_map
  69                    <xsl:when test="oper-status='down' and ../oper-status='down'">
  70                        <xsl:text>p-down</xsl:text>
  71                    </xsl:when>

Lines 72 through 74 specify that if oper-status is 'down', the status variable contains the text down.

content_copy zoom_out_map
  72                    <xsl:when test="oper-status='down'">
  73                        <xsl:text>down</xsl:text>
  74                    </xsl:when>

Lines 75 through 77 specify that if none of the test cases are true, the status variable contains oper-status and admin-status concatenated with a slash as a separator.

content_copy zoom_out_map
  75                    <xsl:otherwise>
  76                        <xsl:value-of select="concat(oper-status, '/', admin-status)"/>
  77                    </xsl:otherwise>

Lines 78 and 79 are closing tags.

content_copy zoom_out_map
  78                </xsl:choose>
  79            </xsl:variable>

Lines 80 through 89 define a variable called desc. An <xsl:choose> instruction populates the variable by selecting the most specific interface description available. If a logical interface description is included in the configuration, it is used to populate the desc variable. If not, the physical interface description is used. If no physical interface description is included in the configuration, the variable remains empty. As always in XSLT, the first <xsl:when> instruction that evaluates as TRUE is executed, and the remainder are ignored.

content_copy zoom_out_map
  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>

The remainder of the script specifies how the operational mode output is displayed.

Lines 90 and 91 specify that the logical interface name is displayed first in the output.

content_copy zoom_out_map
  90            <logical-interface>
  91                <name><xsl:value-of select="name"/></name>

Lines 92 through 94 test whether the desc variable has a nonzero number of characters. If the number of characters is more than zero, the interface description is displayed in the standard location of the admin-status field. (In standard output, the admin-status field is displayed on the second line.)

content_copy zoom_out_map
  92                <xsl:if test="string-length($desc)">
  93                    <admin-status><xsl:value-of select="$desc"/></admin-status>
  94                </xsl:if>

Line 95 specifies that the interface status as defined in the status variable is displayed next.

content_copy zoom_out_map
  95                <admin-status><xsl:value-of select="$status"/></admin-status>

Lines 96 through 103 specify that if you include the protocol argument when you execute the script, only interfaces with that protocol configured are displayed. If you do not include the protocol argument, all interfaces are displayed.

content_copy zoom_out_map
  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>

Lines 104 through 106 are closing tags.

content_copy zoom_out_map
104            </logical-interface>
105        </xsl:template>
106     </xsl:stylesheet>

SLAX Syntax

The SLAX version of the script is as follows:

content_copy zoom_out_map
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;
        }
    }
}

Configuration

Procedure

Step-by-Step Procedure

To download, enable, and test the script:

  1. Copy the XSLT or SLAX script into a text file, name the file interface.xsl or interface.slax as appropriate, and copy it to the /var/db/scripts/op/ directory on the device.

  2. In configuration mode, include the file statement at the [edit system scripts op] hierarchy level and interface.xsl or interface.slax as appropriate.

    content_copy zoom_out_map
    [edit system scripts op]
    user@host# set file interface.(slax | xsl)
    
  3. Issue the commit and-quit command to commit the configuration and to return to operational mode.

    content_copy zoom_out_map
    [edit]
    user@host# commit and-quit
    
  4. Execute the op script by issuing the op interface operational mode command.

Verification

Verifying the Op Script Output

Purpose

Verify that the script behaves as expected.

Action

Issue the show interfaces terse and op interface operational commands and compare the output. The show interfaces terse command displays the standard output. The op interface command displays the customized output.

content_copy zoom_out_map
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--> 

Issue the op interface operational command for different hierarchy levels and review the output. For example:

content_copy zoom_out_map
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 
footer-navigation