Module: Chef::Mixin::Command

Extended by:
Command, Unix, Windows
Includes:
Unix, Windows
Included in:
Command, Provider::Cron, Provider::Deploy, Provider::Env, Provider::ErlCall, Provider::Group, Provider::Ifconfig, Provider::Mount, Provider::Package, Provider::Package::Yum::YumCache, Provider::Route, Provider::Service, Provider::Subversion, Provider::User
Defined in:
lib/chef/mixin/command.rb,
lib/chef/mixin/command/unix.rb,
lib/chef/mixin/command/windows.rb
more...

Defined Under Namespace

Modules: Unix, Windows

Instance Method Summary collapse

Methods included from Windows

popen4

Methods included from Unix

popen4

Instance Method Details

#chdir_or_tmpdir(dir, &block) ⇒ Object

module_function :popen4

[View source]

152
153
154
155
156
157
158
159
160
# File 'lib/chef/mixin/command.rb', line 152

def chdir_or_tmpdir(dir, &block)
  dir ||= Dir.tmpdir
  unless File.directory?(dir)
    raise Chef::Exceptions::Exec, "#{dir} does not exist or is not a directory"
  end
  Dir.chdir(dir) do
    block.call
  end
end

#handle_command_failures(status, command_output, opts = {}) ⇒ Object

[View source]

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/chef/mixin/command.rb', line 117

def handle_command_failures(status, command_output, opts={})
  unless opts[:ignore_failure]
    opts[:returns] ||= 0
    unless Array(opts[:returns]).include?(status.exitstatus)
      # if the log level is not debug, through output of command when we fail
      output = ""
      if Chef::Log.level == :debug || opts[:output_on_failure]
        output << "\n---- Begin output of #{opts[:command]} ----\n"
        output << command_output.to_s
        output << "\n---- End output of #{opts[:command]} ----\n"
      end
      raise Chef::Exceptions::Exec, "#{opts[:command]} returned #{status.exitstatus}, expected #{opts[:returns]}#{output}"
    end
  end
end

#output_of_command(command, args) ⇒ Object

[View source]

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/chef/mixin/command.rb', line 80

def output_of_command(command, args)
  Chef::Log.debug("Executing #{command}")
  stderr_string, stdout_string, status = "", "", nil
  
  exec_processing_block = lambda do |pid, stdin, stdout, stderr|
    stdout_string, stderr_string = stdout.string.chomp, stderr.string.chomp
  end
  
  args[:cwd] ||= Dir.tmpdir
  unless ::File.directory?(args[:cwd])
    raise Chef::Exceptions::Exec, "#{args[:cwd]} does not exist or is not a directory"
  end
  
  Dir.chdir(args[:cwd]) do
    if args[:timeout]
      begin
        Timeout.timeout(args[:timeout]) do
          status = popen4(command, args, &exec_processing_block)
        end
      rescue Timeout::Error => e
        Chef::Log.error("#{command} exceeded timeout #{args[:timeout]}")
        raise(e)
      end
    else
      status = popen4(command, args, &exec_processing_block)
    end
    
    Chef::Log.debug("---- Begin output of #{command} ----")
    Chef::Log.debug("STDOUT: #{stdout_string}")
    Chef::Log.debug("STDERR: #{stderr_string}")
    Chef::Log.debug("---- End output of #{command} ----")
    Chef::Log.debug("Ran #{command} returned #{status.exitstatus}")
  end
  
  return status, stdout_string, stderr_string
end

#run_command(args = {}) ⇒ Object

Parameters

args<Hash>: A number of required and optional arguments

command<String>, <Array>: A complete command with options to execute or a command and options as an Array 
creates<String>: The absolute path to a file that prevents the command from running if it exists
cwd<String>: Working directory to execute command in, defaults to Dir.tmpdir
timeout<String>: How many seconds to wait for the command to execute before timing out
returns<String>: The single exit value command is expected to return, otherwise causes an exception
ignore_failure<Boolean>: Whether to raise an exception on failure, or just return the status
output_on_failure<Boolean>: Return output in raised exception regardless of Log.level

user<String>: The UID or user name of the user to execute the command as
group<String>: The GID or group name of the group to execute the command as
environment<Hash>: Pairs of environment variable names and their values to set before execution

Returns

Returns the exit status of args

[View source]

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/chef/mixin/command.rb', line 58

def run_command(args={})         
  command_output = ""
  
  args[:ignore_failure] ||= false
  args[:output_on_failure] ||= false

  # TODO: This is the wrong place for this responsibility.
  if args.has_key?(:creates)
    if File.exists?(args[:creates])
      Chef::Log.debug("Skipping #{args[:command]} - creates #{args[:creates]} exists.")
      return false
    end
  end
  
  status, stdout, stderr = output_of_command(args[:command], args)
  command_output << "STDOUT: #{stdout}"
  command_output << "STDERR: #{stderr}"
  handle_command_failures(status, command_output, args)
  
  status
end

#run_command_with_systems_locale(args = {}) ⇒ Object

Call #run_command but set LC_ALL to the system’s current environment so it doesn’t get changed to C.

Parameters

args<Hash>: A number of required and optional arguments that will be handed out to #run_command

Returns

Returns the result of #run_command

[View source]

140
141
142
143
144
# File 'lib/chef/mixin/command.rb', line 140

def run_command_with_systems_locale(args={})
  args[:environment] ||= {}
  args[:environment]["LC_ALL"] = ENV["LC_ALL"]
  run_command args
end