github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cloudinit/progress.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloudinit
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/utils"
    10  )
    11  
    12  // progressFd is the file descriptor to which progress is logged.
    13  // This is necessary so that we can redirect all non-progress
    14  // related stderr away.
    15  //
    16  // Note, from the Bash manual:
    17  //   "Redirections using file descriptors greater than 9 should be
    18  //   used with care, as they may conflict with file descriptors the
    19  //   shell uses internally."
    20  const progressFd = 9
    21  
    22  // InitProgressCmd will return a command to initialise progress
    23  // reporting, sending messages to stderr. If LogProgressCmd is
    24  // used in a script, InitProgressCmd MUST be executed beforehand.
    25  //
    26  // The returned command is idempotent; this is important, to
    27  // allow a script to be embedded in another with stderr redirected,
    28  // in which case InitProgressCmd must precede the redirection.
    29  func InitProgressCmd() string {
    30  	return fmt.Sprintf("test -e /proc/self/fd/%d || exec %d>&2", progressFd, progressFd)
    31  }
    32  
    33  // LogProgressCmd will return a command to log the specified progress
    34  // message to stderr; the resultant command should be added to the
    35  // configuration as a runcmd or bootcmd as appropriate.
    36  //
    37  // If there are any uses of LogProgressCmd in a configuration, the
    38  // configuration MUST precede the command with the result of
    39  // InitProgressCmd.
    40  func LogProgressCmd(format string, args ...interface{}) string {
    41  	msg := utils.ShQuote(fmt.Sprintf(format, args...))
    42  	return fmt.Sprintf("echo %s >&%d", msg, progressFd)
    43  }