0

I have a router with a few hundred network interfaces (most of which virtual, naturally). That means that the output of

ip a

shows very many lines which makes management and analysis difficult. Items 1 to 255 are sorted by item number but from 256 the numbers are calculated mod 256 before sorting them which means they are interleaved (e.g. 256, 257, 1, 258, 2, ...):

# ip a s up
256: veth-99-02@br-vxlan-99-02: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ab:cd:ef:99:88:77 brd ff:ff:ff:ff:ff:ff
    inet 10.2.99.254/24 scope global veth-99-02
       valid_lft forever preferred_lft forever
257: vxlan-22-01: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master br-vxlan-20-01 state UNKNOWN group default qlen 1000
    link/ether ab:cd:ef:99:88:77 brd ff:ff:ff:ff:ff:ff
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
258: br-vxlan-22-01: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
    link/ether ab:cd:ef:99:88:77 brd ff:ff:ff:ff:ff:ff
2: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether ab:cd:ef:99:88:66 brd ff:ff:ff:ff:ff:ff

Is there a way to correctly sort this output by number? (They are multi line entries so | sort -n won't do.)

Or, can I select to display numbers e.g. up to 42?

I tried to select by type (ip a s type ...) but that does not really work.

2 Answers 2

2

there is an option that outputs the information each in separate line -o:

-o, -oneline
output each record on a single line, replacing line feeds with the '\' character. This is convenient when you want to count records with wc(1) or to grep(1) the output.

so ip -o a s up |sort -n should do the job; you can then convert back those backslashes to newlines ip -o a s up |sort -n |tr '\\' '\n' if it was needed.

seems when using -o option, it drops some information (I don't know why); then you can use below awk preprocessing alternative before passing to the sort command:

ip a s up \
| awk '{ printf "%s" (NR>1 && /^[0-9]+:/?"\0":(NR>1?"\n":"")) $0 }' \
| sort -nz \
| tr '\0' '\n'

that is adding null character between each block of interfaces, and then using sort with -z sorts the input of null delimited records, and finally revert those null characters back to newlines with tr.

1

With GNU awk:

ip a s up | gawk '
  match($0, /^([0-9]+): /, m) {
    if (prev) ip[prev] = lines
    prev = m[1]
    lines = ""
  }
  { lines = lines $0 RS }
  END {
    if (prev) ip[prev] = lines
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (num in ip) print ip[num]
  }
'
3
  • The quoting of newlines is shell specific (and doesn't work in mine) but otherwise it works, thanks!
    – Ned64
    Aug 7, 2021 at 9:00
  • I don't understand: quoting of what newlines? Do you mean the multi-line string in single quotes? What shell can't do that? Aug 7, 2021 at 12:59
  • The tcsh does not handle it. Its syntax is C-oriented so you need to end a line in a backslash in order to carry on the command in the next line. There may be other shells that cannot handle the single quote handling of newlines but I don't know many.
    – Ned64
    Aug 7, 2021 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.