Question

I'm pretty new to ruby, and I'm trying to troubleshoot an error that puppet is giving me. So far google hasn't helped me get any closer to understanding the problem. Additional information here

When puppet starts a redis init script, it returns the following error:

Debug: Executing '/etc/init.d/redis_6390 start'
Error: Could not start Service[redis_6390]: Execution of '/etc/init.d/redis_6390 start' returned 1: Error: Could not execute posix command: Exec format error - /etc/init.d/redis_6390
Wrapped exception:
Execution of '/etc/init.d/redis_6390 start' returned 1: Error: Could not execute posix command: Exec format error - /etc/init.d/redis_6390
Error: /Stage[main]/Ac_redis_6390/Service[redis_6390]/ensure: change from stopped to running failed: Could not start Service[redis_6390]: Execution of '/etc/init.d/redis_6390 start' returned 1: Error: Could not execute posix command: Exec format error - /etc/init.d/redis_6390
Debug: Class[Ac_redis_6390]: The container Stage[main] will propagate my refresh event

I've found the exact line "Could not execute posix command:" inside the puppet source code.

https://github.com/puppetlabs/puppet/blob/master/lib/puppet/util/execution.rb

  # This is private method.
  # @comment see call to private_class_method after method definition
  # @api private
  #
  def self.execute_posix(command, options, stdin, stdout, stderr)
    child_pid = Puppet::Util.safe_posix_fork(stdin, stdout, stderr) do

      # We can't just call Array(command), and rely on it returning
      # things like ['foo'], when passed ['foo'], because
      # Array(command) will call command.to_a internally, which when
      # given a string can end up doing Very Bad Things(TM), such as
      # turning "/tmp/foo;\r\n /bin/echo" into ["/tmp/foo;\r\n", " /bin/echo"]
      command = [command].flatten
      Process.setsid
      begin
        Puppet::Util::SUIDManager.change_privileges(options[:uid], options[:gid], true)

        # if the caller has requested that we override locale environment variables,
        if (options[:override_locale]) then
          # loop over them and clear them
          Puppet::Util::POSIX::LOCALE_ENV_VARS.each { |name| ENV.delete(name) }
          # set LANG and LC_ALL to 'C' so that the command will have consistent, predictable output
          # it's OK to manipulate these directly rather than, e.g., via "withenv", because we are in
          # a forked process.
          ENV['LANG'] = 'C'
          ENV['LC_ALL'] = 'C'
        end

        # unset all of the user-related environment variables so that different methods of starting puppet
        # (automatic start during boot, via 'service', via /etc/init.d, etc.) won't have unexpected side
        # effects relating to user / home dir environment vars.
        # it's OK to manipulate these directly rather than, e.g., via "withenv", because we are in
        # a forked process.
        Puppet::Util::POSIX::USER_ENV_VARS.each { |name| ENV.delete(name) }

        options[:custom_environment] ||= {}
        Puppet::Util.withenv(options[:custom_environment]) do
          Kernel.exec(*command)
        end
      rescue => detail
        Puppet.log_exception(detail, "Could not execute posix command: #{detail}")
        exit!(1)
      end
    end
    child_pid
  end
  private_class_method :execute_posix

What do these lines do? I'm trying to understand what is throwing this exception.

        options[:custom_environment] ||= {}
        Puppet::Util.withenv(options[:custom_environment]) do
          Kernel.exec(*command)
        end
Was it helpful?

Solution 2

I'm going to assume the two pieces which are confusing are ||= and *command.

||= is a conditional assignment operator which only performs an assignment when the variable on it's left side evaluates to false, typically when it is nil or false. This is very commonly used with instance variables, or hash members, both of which evaluate to nil when unset.

* is a splat operator and is used to convert an Array to a series of arguments passed into a method. The following examples are identical:

# Pass colors directly to use_colors.
use_colors('red', 'green', 'blue')

# Unpack an Array into an argument list for use_colors.
colors = ['red', 'green', 'blue']
use_colors(*colors)

Likewise, you can use the splat operator in a method declaration to receive the remaining passed arguments as an Array:

# This method can accept any number of colors, including zero.
def use_colors(*colors)
  colors.each do |color|
    puts "Using color: #{color}!"
  end
end

OTHER TIPS

options[:custom_environment] ||= {} means "assign '{}' if options[:custom_environment] is nil or false".

And execute system command command.

command is a Array, and first value of it is command itself, other values of array are argument of the system command.

I hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top