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