Intro

This post is intended for Network Engineers who want to quickly get up to speed with JunOS.  It’s best read if you already know the protocols and have experience with Cisco IOS.  We won’t be going into detail of how protocols work (like OSPF, IS-IS, etc) and it also is not intended to be a “certification post”.  The focus is going to be heavy on the implementation of JunOS CLI and I’ll be using comparisons with Cisco IOS throughout.  Note, that all of my code examples will be from my vSRX firewalls in my lab.

With that all that said, let’s get into the basics.

JunOS CLI Modes

In Cisco IOS we have three modes:

  • User mode
  • Exec mode
  • Configuration mode
    • Within config mode, we have the hierarchy of sub-config modes

We can see all three here and how to navigate between them:

Router>enable
Router#configure terminal

Router(config)#interface g0/0
Router(config-if)#

You can also see what happens when you go into one of the sub-configuration modes. In IOS, note that the prompt doesn’t show which interface we are configuring. It only shows that we are under interface configuration mode. This is different than JunOS.

JunOS has three modes as well, but they are slightly different:

  • UNIX shell
    • When you log in as root, you are placed here.
    • You can use normal UNIX/Linux shell commands here.
  • Operational mode
    • From the UNIX shell, use the cli command to get here.
    • This mode is equivalent to the user & exec modes in IOS.
    • Use it for monitoring & troubleshooting with show, ping, clear commands and others.
    • This is mainly read-only.
  • Configuration mode
    • From operational mode, use the configure command.
    • This is equivalent to config modes in IOS.
    • You can use both read & write commands here, and use it to configure the device.

Let’s take a look at the modes and how to navigate between them:

root@:~ # cli
root> configure
Entering configuration mode

[edit]
root# edit interfaces ge-0/0/0

[edit interfaces ge-0/0/0]
root#

Note the difference between JunOS & IOS. The prompt stays the same, but you can see which mode we are in above the prompt. Also note that you can see exactly where you are in the hierarchy. In this case we can see exactly which interface we are configuring, which is different than IOS where we just see that we are configuring an interface, but not which one.

Configuration Types

Cisco IOS has two configurations:

  • Startup Config
    • Backup of configuration in NVRAM.  Survives a reboot.
  • Running Config
    • Active configuration on the device.  Does not survive a reboot.

There are two important consequences to this design.  The first is that changes to the running config are automatically applied.  As soon as you hit enter on a command, it’s live.  The second is that changes to the running config are not automatically saved to the startup configuration.  If you don’t manually save the config, it won’t survive a reboot.

JunOS has two configurations as well, but it’s very different.  In fact, if you have experience with IOS-XR you’ll find that JunOS is similar to XR, but not regular IOS/XE.  The two configurations are:

  • Active Config
    • Currently running on the device.  Also survives a reboot.
  • Candidate Config
    • Uncommitted changes that can be merged with the active config. 

The result of this design is that no configuration is applied until they are committed. There is also error checking built in to the commits. If there are syntax errors, the commit will be rejected. The other important thing is that every successful commit is saved to a database for versioning. That means we’ll be able to rollback to previous configurations if needed. We’ll dig into this more. First, let’s take a look at a commit.

In this example, I’m going to apply an IP address to an interface and commit the changes.

[edit interfaces ge-0/0/0]
root# set unit 0 family inet address 10.1.1.2/24

[edit interfaces ge-0/0/0]
root# commit
[edit]
  'system'
    Missing mandatory statement: 'root-authentication'
error: commit failed: (missing mandatory statements)

As you can see, the commit failed. This is because it’s the first configuration I’ve tried to commit on the device. With JunOS, you must set a new root password in order to commit changes. I’ll set that password, and try to commit again.

[edit interfaces ge-0/0/0]
root# top

[edit]
root# set system root-authentication plain-text-password
New password:
Retype new password:

[edit]
root# commit
commit complete

The first thing I did was use the top command to navigate back to top of the hierarchy. Note that you can also use the up command to move up one level. Next I set the root password and committed the config. As you can see, it was successful.

There are a few other commands we can use to commit configs as well:

  • commit and-quit
    • Exits to operational mode once the commit is complete.
  • commit check
    • Checks the uncommitted changes for syntax errors.  This doesn’t commit the config, so you’ll have to commit the config after running this check if it’s successful.
  • commit at
    • Schedules a time for the commit to occur.
  • commit confirmed
    • This commits the changes, but will roll them back if another commit is not entered.
    • You would use this if you are afraid the change will lock you out of the device.

Before you commit, you can also view the difference between the active config and the candidate config:

root# show | compare
[edit interfaces]
+   lo0 {
+       unit 0 {
+           family inet {
+               address 2.2.2.2/24;
+           }
+       }
+   }

You can see the ‘+’ sign, meaning that this configuration is going to be added. If there was a ‘-‘ it would mean that configuration would be removed. We can also see that by comparing the candidate configuration and one of the old rollbacks.

root# show | compare rollback 0
[edit interfaces]
+   lo0 {
+       unit 0 {
+           family inet {
+               address 2.2.2.2/24;
+           }
+       }
+   }

A rollback identifies previous versions of active configurations.  You can view a list like this:

root# rollback ?
Possible completions:
  <[Enter]>            Execute this command
  0                    2021-02-11 15:31:09 UTC by root via cli
  1                    2021-02-11 15:09:09 UTC by root via cli
  2                    2021-02-11 14:30:20 UTC by root via other
  revision             Rollback to given configuration revision
  |                    Pipe through a command

We can see that this router has three versions. Version 0 is always the current active configuration on the box. From there we can start going further and further back in time. To rollback, you can enter the number to load that configuration into the candidate config. Note you’ll still need to commit the rollback.

root# rollback 1
load complete

[edit]
root# show | compare
[edit interfaces]
-   lo0 {
-       unit 0 {
-           family inet {
-               address 2.2.2.2/24;
-           }
-       }
-   }

[edit]
root# commit
commit complete

You can also view and compare configurations from operational mode as well:

  • show config | compare rollback #
  • show system rollback #
  • show system rollback # compare #

Syntax Completion & Help

Just like Cisco IOS, you can use tabs & question marks for syntax completion & context sensitive help.  The difference is that with JunOS you can use either space or tab for completion.  Tab will also complete user defined variables or names.

While you can use question marks for context help, you can also use the help command.

  • help apropos <string>
  • help reference <string>
  • help topic <string>
  • help tip cli
    • This will give you tips about using the cli

JunOS Hierarchy

We’ve seen some of the JunOS hierarchy already, but I just wanted to go over some more notes on how to navigate it and run configuration commands.

First, you can use the edit command to move down the hierarchy and the up command to move back up.

[edit]
root#

[edit]
root# edit interfaces

[edit interfaces]
root# edit ge-0/0/0

[edit interfaces ge-0/0/0]
root# edit unit 0

[edit interfaces ge-0/0/0 unit 0]
root# up

[edit interfaces ge-0/0/0]
root# top

[edit]
root#

You can see the that JunOS always tells you where in the hierarchy you are. Note that you don’t have to go into each level of hierarchy to run commands. You can actually do them from the root, or any level of the hierarchy that makes sense to you. Here’s an example of putting an IP address on an interface from a few different levels:

[edit]
root# set interfaces ge0/0/0 unit 0 family inet address 10.1.1.2/24

---- OR ----

[edit]
root# edit interfaces ge-0/0/0

[edit interfaces ge-0/0/0]
root# set unit 0 family inet address 10.1.1.2/24




---- OR ----

[edit]
root# edit interfaces

[edit interfaces]
root# set ge-0/0/0 unit 0 family inet address 10.1.1.2/24

As you can see, we did the same thing from three different levels of the hierarchy.  If you know the entire path you can do everything from the root, or you can drill down to the specific “sub-config mode” that you need.

JunOS Show Commands

You can run show commands in operational mode and configuration mode.  The mode you run the command in changes the output you will receive.  Let’s go over operational mode first.

In operational mode, the show command checks the state of the system.  This is very similar to show commands in Cisco IOS.  Here’s an example:

root> show interfaces ge-0/0/0
Physical interface: ge-0/0/0, Enabled, Physical link is Up
  Interface index: 135, SNMP ifIndex: 508
  Link-level type: Ethernet, MTU: 1514, LAN-PHY mode, Link-mode: Full-duplex,
  Speed: 10Gbps, BPDU Error: None, Loop Detect PDU Error: None,
  Ethernet-Switching Error: None, MAC-REWRITE Error: None, Loopback: Disabled,
  Source filtering: Disabled, Flow control: Enabled
  Device flags   : Present Running
---- Output omitted for brevity ----

You can specify how much detail you want with each command as well. For example, the equivalent of show ip interface brief in IOS would be:

root> show interfaces terse
Interface               Admin Link Proto    Local                 Remote
ge-0/0/0                up    up
ge-0/0/0.0              up    up   inet     10.1.1.2/24
gr-0/0/0                up    up
ip-0/0/0                up    up
lsq-0/0/0               up    up

There are other keywords for varying levels of detail.  In order from least to most detail are:

  • terse
  • brief
  • detail
  • extensive

In configuration mode, the show commands are use to check configurations.  It is also relative to where you are in the hierarchy.

[edit]
root# show interfaces ge-0/0/0
unit 0 {
    family inet {
        address 10.1.1.2/24;
    }
}

[edit]
root# edit interfaces ge-0/0/0

[edit interfaces ge-0/0/0]
root# show
unit 0 {
    family inet {
        address 10.1.1.2/24;
    }
}

Filtering With Pipes

In Cisco IOS we can filter using pipes.  JunOS has the same thing.  Here’s an example with the show interfaces command:

root> show interfaces terse | match ge-0/0/0
ge-0/0/0                up    up
ge-0/0/0.0              up    up   inet     10.1.1.2/24

This is very similar to IOS, so I’m not going to go through all of the variations. Instead, I want to go over something that is different from IOS, and that’s how to display the configuration. Let’s take a quick look at the configuration for the interfaces:

root> show configuration interfaces
ge-0/0/0 {
    unit 0 {
        family inet {
            address 10.1.1.2/24;
        }
    }
}

By default, the format shows the configuration hierarchy. We can use pipes to change this. For example, let’s say we want to look at it in either XML or JSON:

root> show configuration interfaces ge-0/0/0 | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/20.4R0/junos">
    <configuration junos:commit-seconds="1613057658" junos:commit-localtime="2021-02-11 15:34:18 UTC" junos:commit-user="root">
            <interfaces>
                <interface>
                    <name>ge-0/0/0</name>
                    <unit>
                        <name>0</name>
                        <family>
                            <inet>
                                <address>
                                    <name>10.1.1.2/24</name>
                                </address>
                            </inet>
                        </family>
                    </unit>
                </interface>
            </interfaces>
    </configuration>
    <cli>
        <banner></banner>
    </cli>
</rpc-reply>

root> show configuration interfaces ge-0/0/0 | display json
{
    "configuration" : {
        "@" : {
            "junos:commit-seconds" : "1613057658",
            "junos:commit-localtime" : "2021-02-11 15:34:18 UTC",
            "junos:commit-user" : "root"
        },
        "interfaces" : {
            "interface" : [
            {
                "name" : "ge-0/0/0",
                "unit" : [
                {
                    "name" : 0,
                    "family" : {
                        "inet" : {
                            "address" : [
                            {
                                "name" : "10.1.1.2/24"
                            }
                            ]
                        }
                    }
                }
                ]
            }
            ]
        }
    }
}

Along the same lines, another really useful feature is being able to display the set commands instead of viewing the hierarchical config.

root> show configuration interfaces ge-0/0/0 | display set
set interfaces ge-0/0/0 unit 0 family inet address 10.1.1.2/24

This is useful for copy/pasting or being able to view the commands in a much more condensed manner. We can also use multiple pipes to parse the entire configuration for what you need. This is more useful if you have a ton of configuration on the device, but you can see the results here with our example:

root> show configuration | display set | match ge-0/0/0
set interfaces ge-0/0/0 unit 0 family inet address 10.1.1.2/24

Conclusion & Next Posts

Hopefully after reading this you are comfortable navigating the JunOS CLI.  I didn’t really go into configurations here, just more of the CLI basics and it’s similarities with Cisco IOS.  My plan is to go over configurations in the next couple of posts.  I’m going to focus mostly on routing, so the next post will be routing basics on JunOS, followed by some routing protocol and policy configurations.