JUNOS の便利なパイプ操作まとめ

JUNOS のパイプ ( | ) を使ったコマンド操作が、便利な割にあまり日本語の情報がない(？)ようなので、思いつくものをまとめて見ました。
快適な JUNOS ライフの一助になれば幸いです。

## 目次
[match](#match)
[find](#find)
[no-more](#no-more)
[display](#display)
　- [display set](#display-set)
　- [display xml](#display-xml)
　- [display json](#display-json)
　- [display inheritance](#display-inheritance)
[compare](#compare)
[count](#count)
[last](#last)
[save](#save)

## ユースケース
私が思いつくユースケースをいくつか並べてみました。
これやりたかったんだ～というのがあればジャンプ先を参照ください。

### よく使うやつ
・特定の文字列を含む行のみを出力したい(要するに grep したい) → [match](#match) (または [grep](#match) )
・コマンド出力結果から文字列を検索したい(要するに vi の検索みたいなことがしたい) → [find](#find)
・コマンド出力結果を全部一気に表示したい → [no-more](#no-more)
・コンフィグを階層形式ではなく set 形式(コマンド形式)で表示したい → [display set](#display-set)
・編集中のコンフィグと稼働中のコンフィグとの差分を表示したい → [compare](#compare)
・編集中のコンフィグと保存しているコンフィグファイルとの差分を表示したい → [compare](#compare)
・特定の文字列を含む行の行数をカウントしたい → [count](#count)
・出力結果の末尾 n 行分のみを表示させたい → [last](#last)
・コマンド表示結果をファイルに保存したい → [save](#save)
・コマンド表示結果を外部に保存したい → [save](#save)


### 機会は少ないけど便利なやつ
・コマンド出力結果をXML形式で表示したい → [display xml](#display-xml)
・コマンド出力結果をJSON形式で表示したい → [display json](#display-json)
・編集中のコンフィグと過去のコンフィグとの差分を表示したい → [compare rollback](#compare-rollback)
・match で and 検索がしたい → [match](#match) (または [grep](#match) )
・match で or 検索がしたい → [match](#match) (または [grep](#match) )
・groups の設定から継承されたコンフィグ内容も表示させたい → [display inheritance](#display-inheritance)
・暗黙的なデフォルトコンフィグも含めて表示させたい → [display inheritance default](#display-inheritance-default)

## match
ただ grep と同じことをするだけです。それだけ！
match の代わりに grep そのものも使えます。(ならなぜ match があるんだろう。。。)

```
root> show interfaces terse | match ge-0/0/2
ge-0/0/2                up    up
ge-0/0/2.0              up    up   inet     192.168.2.1/24

root> show interfaces terse | grep ge-0/0/2
ge-0/0/2                up    up
ge-0/0/2.0              up    up   inet     192.168.2.1/24
```

### AND検索, OR検索
複数の文字列 AND 検索がしたい時はパイプをそのまま並べることで可能です。
OR をしたい時は "(hoge|fuga)" のように文字列を並べることでできます。

```
★ AND
root> show log messages | match down | match ge-0/0/0
Jun  7 06:43:28   rpd[1644]: EVENT <UpDown> ge-0/0/0 index 135 <Up Broadcast Multicast> address #0 0.c.29.35.41.91
Jun  7 06:44:32   rpd[1644]: EVENT <UpDown> ge-0/0/0.0 index 73 <Broadcast Multicast> address #0 0.c.29.35.41.91
Jun  7 06:44:32   rpd[1644]: EVENT <UpDown> ge-0/0/0 index 135 <Broadcast Multicast> address #0 0.c.29.35.41.91
Jun  7 06:44:32   mib2d[1643]: SNMP_TRAP_LINK_DOWN: ifIndex 510, ifAdminStatus up(1), ifOperStatus down(2), ifName ge-0/0/0
Jun  7 06:48:48   rpd[1479]: EVENT <UpDown> ge-0/0/0 index 135 <Up Broadcast Multicast> address #0 0.c.29.35.41.91
Jun  7 06:48:57   rpd[1479]: EVENT <Delete UpDown> ge-0/0/0.0 index 73 <Broadcast Multicast> address #0 0.c.29.35.41.91
Jun  7 06:48:57   mib2d[1478]: SNMP_TRAP_LINK_DOWN: ifIndex 520, ifAdminStatus down(2), ifOperStatus down(2), ifName ge-0/0/0.0

★ OR
root> show interfaces terse | match "(ge-0/0/0|ge-0/0/1|lo0)"
ge-0/0/0                up    up
ge-0/0/0.0              up    up   inet     192.168.0.1/24
ge-0/0/1                up    up
ge-0/0/1.0              up    up   inet     192.168.1.1/24
lo0                     up    up
lo0.0                   up    up   inet     1.1.1.1             --> 0/0
lo0.16384               up    up   inet     127.0.0.1           --> 0/0
lo0.16385               up    up   inet     10.0.0.1            --> 0/0
lo0.32768               up    up
```



## find
指定した文字列を含む行から出力を開始します。
n キーで次にマッチする行に移ります。

★サンプル★

```
root> show interfaces terse | find ge-0/0/1
ge-0/0/1                up    up
ge-0/0/1.0              up    up   inet     192.168.1.1/24
ge-0/0/2                up    up
ge-0/0/2.0              up    up   inet     192.168.2.1/24
ge-0/0/3                up    up
ge-0/0/3.0              up    up   inet     192.168.3.1/24
ge-0/0/4                up    up
ge-0/0/4.0              up    up   inet     192.168.4.1/24
・・・(以下略)
```

## no-more
通常は screen-length の長さでターミナル出力が止まりますが、no-more を使うことで一気に出力させることができます。
(Linux でいう more に対する cat のような感じでしょうか)

## display
display の後に続くオプションに応じて、表示方法を色々と加工できます。

### display set 
show configuration コマンド (またはコンフィグモードでの show コマンド) に対してのみ有効なオプションです。
コンフィグを階層形式ではなく set 形式で表示します。

★サンプル★

```
root> show configuration | display set
set version 15.1X49-D160.2
set system root-authentication encrypted-password "$5$R30/x195$Sts5zwOfMLAPtbstZXvViD.CQ/a5xiAYR2zc4Dcoyd6"
set system services ssh
set interfaces ge-0/0/0 unit 0 family inet address 192.168.0.1/24
set interfaces ge-0/0/1 unit 0 family inet address 192.168.1.1/24
set interfaces ge-0/0/2 unit 0 family inet address 192.168.2.1/24
set interfaces ge-0/0/3 unit 0 family inet address 192.168.3.1/24
set interfaces ge-0/0/4 unit 0 family inet address 192.168.4.1/24
・・・(以下略)
```

### display xml
コマンド表示結果を xml 形式で表示できます。
Netconf を使って情報取得したりコンフィグを投入したりしたい時にいちいちドキュメント見る必要がなくて便利です。パースもやり易いです。

```
root> show configuration | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1X49/junos">
    <configuration junos:commit-seconds="1560156671" junos:commit-localtime="2019-06-10 08:51:11 UTC" junos:commit-user="root">
            <version>15.1X49-D160.2</version>
            <system>
                <root-authentication>
                    <encrypted-password>$5$R30/x195$Sts5zwOfMLAPtbstZXvViD.CQ/a5xiAYR2zc4Dcoyd6</encrypted-password>
                </root-authentication>
                <services>
                    <ssh>
                    </ssh>
                </services>
            </system>
            <interfaces>
                <interface>
                    <name>ge-0/0/0</name>
                    <unit>
                        <name>0</name>
                        <family>
                            <inet>
                                <address>
                                    <name>192.168.0.1/24</name>
                                </address>
                            </inet>
                        </family>
                    </unit>
                </interface>
・・・(以下略)
```

### display json
コマンド表示結果を json 形式で表示できます。
(古いバージョンだと対応してないかも)

```
root> show configuration | display json
{
    "configuration" : [
    {
        "attributes" : {"junos:commit-seconds" : "1560156671",
                        "junos:commit-localtime" : "2019-06-10 08:51:11 UTC",
                        "junos:commit-user" : "root"
                       },
        "version" : [
        {
            "data" : "15.1X49-D160.2"
        }
        ],
        "system" : [
        {
            "root-authentication" : [
            {
                "encrypted-password" : [
                {
                    "data" : "$5$R30/x195$Sts5zwOfMLAPtbstZXvViD.CQ/a5xiAYR2zc4Dcoyd6"
                }
                ]
            }
            ],
            "services" : [
            {
                "ssh" : [
                {
                }
                ]
            }
            ]
        }
        ],
        "interfaces" : [
        {
            "interface" : [
            {
                "name" :
                {
                    "data" : "ge-0/0/0"
                },
                "unit" : [
                {
                    "name" :
                    {
                        "data" : "0"
                    },
                    "family" : [
                    {
                        "inet" : [
                        {
                            "address" : [
                            {
                                "name" :
                                {
                                    "data" : "192.168.0.1/24"
                                }
                            }
                            ]
                        }
                        ]
                    }
                    ]
                }
                ]
            },
・・・(以下略)
```

### display inheritance
groups でのコンフィグが apply されている階層において、その groups から継承されるコンフィグ内容をコマンド出力結果に表示することができます。
groups で書いた設定内容が自分の意図した通りとなっているかをチェックするのに便利だと思います。
あと、他人が書いた秘伝の groups がゴチャゴチャしててよくわからん、、、という時にも便利です。

★サンプル★

```
★ groups の設定内容
root> show configuration groups
MTU {
    interfaces {
        <ge-*> {
            mtu 9000;
        }
    }
}

root> show configuration apply-groups
apply-groups MTU;

★ groups から継承された内容がコメント付きで表示される
root> show configuration interfaces | display inheritance
ge-0/0/0 {
    ##
    ## '9000' was inherited from group 'MTU'
    ##
    mtu 9000;
    unit 0 {
        family inet {
            address 192.168.0.1/24;
        }
    }
}
ge-0/0/1 {
    ##
    ## '9000' was inherited from group 'MTU'
    ##
    mtu 9000;
    unit 0 {
        family inet {
            address 192.168.1.1/24;
        }
    }
}
・・・(以下略)

★ コメントが邪魔な時は no-comments オプションで消せる
root> show configuration interfaces | display inheritance no-comments
ge-0/0/0 {
    mtu 9000;
    unit 0 {
        family inet {
            address 192.168.0.1/24;
        }
    }
}
ge-0/0/1 {
    mtu 9000;
    unit 0 {
        family inet {
            address 192.168.1.1/24;
        }
    }
}
・・・(以下略)
```

### display inheritance default
display inheritance に default というオプションをつけることで、コンフィグには表示されないデフォルトコンフィグを表示させることもできます。
※言葉がややこしいですが、ここでの「デフォルトコンフィグ」とは、コンフィグに明示的に書かれていない場合に暗黙的に適用されるコンフィグを指します。 ("初回起動時に書かれているコンフィグ" ではないです)

```
root> show configuration system | display inheritance defaults
##
## 'ports' was inherited from group 'junos-defaults'
##
ports {
    ##
    ## 'console' was inherited from group 'junos-defaults'
    ## 'vt100' was inherited from group 'junos-defaults'
    ##
    console type vt100;
}
root-authentication {
    encrypted-password "$5$R30/x195$Sts5zwOfMLAPtbstZXvViD.CQ/a5xiAYR2zc4Dcoyd6"; ## SECRET-DATA
}
##
## 'login' was inherited from group 'junos-defaults'
##
login {
    ##
    ## 'password' was inherited from group 'junos-defaults'
    ##
    password {
        ##
        ## '6' was inherited from group 'junos-defaults'
        ##
        minimum-length 6;
        ##
        ## 'set-transitions' was inherited from group 'junos-defaults'
        ##
        change-type set-transitions;
        ##
        ## '1' was inherited from group 'junos-defaults'
        ##
        minimum-changes 1;
        ##
        ## 'sha256' was inherited from group 'junos-defaults'
        ##
        format sha256;
    }
}
・・・(以下略)
```


## compare
commit前の編集中のコンフィグと稼働中のコンフィグとの差分を表示できます。

```
★コンフィグを編集してみる
[edit]
root# rename interfaces ge-0/0/0 unit 0 family inet address 192.168.0.1/24 to address 192.168.0.100/24

★差分を表示
[edit]
root# show | compare
[edit interfaces ge-0/0/0 unit 0 family inet]
+       address 192.168.0.100/24;
-       address 192.168.0.1/24;
```

### compare rollback
rollback オプションを使うことで、編集中のコンフィグと過去に稼働中だったコンフィグとの差分を表示できます。
だいたいは稼働中のコンフィグと過去のコンフィグとの差分をすぐに見たい時に使う場合が多いと思います。
( rollback n コマンドしてから show | compare しても全く同じことが出来ますが、不用意に rollback するのは危険です)

```
[edit]
root# show | compare rollback 1
[edit]
+ groups {
+     MTU {
+         interfaces {
+             <ge-*> {
+                 mtu 9000;
+             }
+         }
+     }
+ }
+ apply-groups MTU;
[edit interfaces ge-0/0/0 unit 0 family inet]
+       address 192.168.0.100/24;
-       address 192.168.0.1/24;
```

## count
コマンドの具体的な結果は表示せずに、その行数を表示します。
match などと併用して使うことが多いかな〜と思います。
※例えば OSPF や BGP などで、ネイバー確立できているものの数だけをとりあえず知りたい時とか

```
★VRRP のマスターとなっているグループの数だけを知りたい
root> show vrrp | match master | count
Count: 11 lines

root> show vrrp | match backup | count
Count: 0 lines
```


## last
コマンド表示結果の最後 n 行を表示します。
( tail のようなもの)

```
root> show log messages | last 30
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: cannot signal 'SCC Chassisd Process', signal 1, no pid
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying nsd(76)
Jun  7 06:49:11    PFE_SCREEN_MT_CFG_EVENT: [GENCFG_OP_DELETE]: screen name - untrust-screen
Jun  7 06:49:11    received GENCFG_OP_CHANGE for host http port 80
Jun  7 06:49:11    received GENCFG_OP_CHANGE for host https port 443
Jun  7 06:49:11    received GENCFG_OP_CHANGE for host rpm tcp port 7
Jun  7 06:49:11    received GENCFG_OP_CHANGE for host rpm udp port 7
Jun  7 06:49:11   nsd[1506]: nsd_apbr_config_root_read: Entered
Jun  7 06:49:11    received GENCFG_OP_CHANGE for host reverse telnet port 2900
Jun  7 06:49:11    received GENCFG_OP_CHANGE for host reverse ssh port 2901
Jun  7 06:49:11    zone_handler: zone delete zone_id 6
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: signaling 'Network security daemon', pid 1506, signal 1, status 0 with notification errors enabled
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying rtlogd(85)
Jun  7 06:49:11    zone_handler: zone delete zone_id 7
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: signaling 'Security Log Daemon', pid 1522, signal 1, status 0 with notification errors enabled
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying utmd(86)
Jun  7 06:49:11   utmd[1523]: UTMD_EWF_CAT_OBSOLETE: EWF category 'Enhanced_Racism_and_Hate' was obsoleted by new category 'Enhanced_Intolerance'
Jun  7 06:49:11   utmd[1523]: UTMD_EWF_CAT_OBSOLETE: EWF category 'Enhanced_Potentially_Damaging_Content' was obsoleted by new category 'Enhanced_Suspicious_Content'
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: signaling 'UTM Daemon', pid 1523, signal 1, status 0 with notification errors enabled
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying syshmd(89)
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: signaling 'System Health Management Daemon', pid 1526, signal 1, status 0 with notification errors enabled
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying sdk-vmmd(97)
Jun  7 06:49:11   mgd[2457]: UI_AUTH_EVENT: Authenticated user 'root' at permission level 'super-user'
Jun  7 06:49:11   mgd[2457]: UI_LOGIN_EVENT: User 'root' login, class 'super-user' [2457], ssh-connection '', client-mode 'cli'
Jun  7 06:49:11   mgd[2457]: UI_CMDLINE_READ_LINE: User 'root', command 'show configuration system root-authentication encrypted-password | display inheritance | display set | save /var/tmp/ptmp1 '
Jun  7 06:49:11   mgd[2457]: PVIDB Feature list Count: 30
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: signaling 'App-engine virtual machine management process', pid 1508, signal 1, status 0 with notification errors enabled
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying l2ald(106)
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress: signaling 'Layer 2 address flooding and learning process', pid 1480, signal 1, status 0 with notification errors enabled
Jun  7 06:49:11   mgd[1673]: UI_COMMIT_PROGRESS: Commit operation in progress:  notifying eventd(107)
```



## save
コマンドの結果をファイルとして保存できます。
ファイルはローカルにも外部サーバにも保存できます。

```
★装置のローカルに保存
root> show configuration | save 20190610_test_config..txt
Wrote 76 lines of output to '20190610_test_config..txt'

root> file ls
/cf/root/:
.cshrc
.history
.login
.profile
20190610_test_config..txt
```

```
★外部サーバに保存
root> show configuration | save scp://centos@10.254.0.193/home/centos/20190610_test_config.txt
centos@10.254.0.193's password:
tempfile                                                                                                                                                                              100% 1375     1.3KB/s   00:00
Wrote 76 lines of output to 'scp://centos@10.254.0.193/home/centos/20190610_test_config.txt'

★外部サーバで確認
[centos@localhost ~]$ ls
20190610_test_config.txt
```

## 正規表現
この他、[正規表現](https://www.juniper.net/documentation/en_US/junos/topics/topic-map/filtering-operational-command.html#id-using-regular-expressions-with-the-pipe-symbol-to-filter-junos-os-command-output) も色々使えます。