The project team has addressed the concerns raised during the initial
discussion and produced an updated specification which I've placed in
the materials directory. It's also included below. Changes made:
* Made it clear that this case is specific to the dladm command
* Field separator is now ':' instead of '|'
* Escaping of field separator is only done if multiple fields are
requested
* Clarified why a space was not used as a field separator
* Added proposed man page changes including examples
The timer for this case has been reset and will expire on June 24th,
2008.
Overview
========
This case proposes to revise the parsable output format for dladm(1M)
to be both robust and easy to parse.
Stability level is Committed. Release Binding is Minor.
Background
==========
In general, it's helpful for building administrative scripts as well as
test cases that there be some way to cause commands to issue output in
a format that is stable and easy for scripts to parse. While dladm(1M)
currently provides a parsable output mode, it is not that easy to
parse, especially from a shell:
# dladm show-link -p
LINK="e1000g0" CLASS="phys" MTU="1500" STATE="up" OVER=""
LINK="e1000g1" CLASS="phys" MTU="1500" STATE="unknown" OVER=""
LINK="e1000g2" CLASS="phys" MTU="1500" STATE="unknown" OVER=""
LINK="e1000g3" CLASS="phys" MTU="1500" STATE="unknown" OVER=""
Although one might think that "eval" could be used in the shell to
access the set of values one line at a time, this has major pitfalls:
* Each eval runs the risk possibly clobbering variables already in
use by the script. This means that any time a new field is
added, there is small but very real potential to break any
script that happened to use that field name as a local variable.
* Use of eval presents a significant security risk: any command
where a non-privileged user might gain control over any field's
value makes eval as root (say, in an admin script) unsafe.
Proposal
========
We propose that parsable output employ a simple field separator scheme
similar to what is already used by "zoneadm list -p":
$ zoneadm list -p
0:global:running:/::native:shared
Further, we propose that the existing "-o" switch (which is used to
enumerate fields to display) be required in parsable output mode.
This ensure that we will be able to add new fields in the future
without potentially breaking existing scripts.
Note:
* Fields with no value will be shown as being empty (see the
example below), rather than "-" or "--", as might be used in
normal output.
* As before, headers will be omitted in parsable output mode.
* Since it's possible that a field value could contain a
literal ":", parsable output will escape literal ":" as
"\:", and literal "\" as "\\". Escaping will be done only
when multiple values are requested via the -o option,
allowing singletons to be used directly via var=`dladm ...`.
As it happens, this escape format is already handled
automatically by the "read" and "while read" shell
constructs, ensuring that parsing remains simple when
multiple values are requested. Please refer to the examples
in the proposed manual page changes.
Output format examples:
# dladm show-link -o link,over,state
LINK OVER STATE
e1000g0 -- up
e1000g1 -- unknown
e1000g2 -- unknown
e1000g3 -- unknown
# dladm show-link -p
dladm: output field list (-o) required in parsable output mode
# dladm show-link -p -o link,over,state
e1000g0::up
e1000g1::unknown
e1000g2::unknown
e1000g3::unknown
Note that this is a change to a Committed interface, but it is a
relatively safe change. The Solaris 10 parsable output format was
not usable and was already modified in Nevada build 83 to the
format described in the Background section. Changing the format
again doesn't break anything new, and the project team is aware of
the existing consumers of this format since they needed to be
altered in build 83.
Note also that space (" ") as a separator is not compatible with
null representation of empty field values. Shell read(1) treats
sequential whitespace characters as a single separator.
Man Page Changes
================
Under all usages for:
-p, --parsable
Change text to:
Displays output using a stable machine-parsable format. The -o
option is required with -p. Refer to "Parsable Output Format"
for more information.
Under "Parsable Output Format", replace the text with the following:
(somewhat lifted from the zoneadm man page):
Many dladm subcommands have an option that displays output in a
machine-parsable format. The output format is one or more lines
of colon (":") delimited fields. Possible fields are specific to
the subcommand used and are listed under the entry for the
corresponding -o option. Output includes only those fields
requested via the -o option, in the order requested.
When multiple fields are requested, any literal ":" characters
will be escaped by a backslash ("\") before being output.
Similarly, literal backslash characters will also be escaped
("\\"). This escape format is parsable by using shell read(1)
functions with the environment variable IFS=: (see Example 11).
Note that escaping is not done when only a single field is
requested.
Under EXAMPLES, add:
Example 10, Using parsable output to capture a single field
This example saves the mtu of link net0 to a variable named "mtu".
# mtu=`dladm show-link -p -o mtu net0`
Example 11, Using parsable output to iterate over links in a script
This example script prints the state of each link on the system.
# dladm show-link -p -o link,state | while IFS=: read link state; do
print "Link $link is in state $state"
done