Uploaded image for project: 'Puppet'
  1. Puppet
  2. PUP-6675

Puppet::Util::Execution.execute 'hostname' returns nothing as daemon

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • Normal
    • Resolution: Fixed
    • None
    • PUP 5.1.0
    • None
    • Bug Fix
    • Hide
      An issue where some commands run via {{exec}} or in providers would be prevented from running by selinux - because Puppet would redirect their output to a file in /tmp - should be addressed. Puppet now uses a pipe to get stdout from the executed process. This has one known side effect: on Windows if a Puppet agent run is killed, a new agent run will be prevented from starting by Puppet's lockfile until any subprocesses started by the previous agent run have completed.
      Show
      An issue where some commands run via {{exec}} or in providers would be prevented from running by selinux - because Puppet would redirect their output to a file in /tmp - should be addressed. Puppet now uses a pipe to get stdout from the executed process. This has one known side effect: on Windows if a Puppet agent run is killed, a new agent run will be prevented from starting by Puppet's lockfile until any subprocesses started by the previous agent run have completed.

    Description

      When Puppet::Util::Execution.execute 'hostname' is invoked by Puppet running as a daemon, no output is written. This seems to be exclusive to hostname, and may be restricted to certain Linux versions. I've tried it on RedHat 7 (64-bit).

      This can happen in a provider when using commands :hostname => 'hostname', and then invoking hostname. The root appears to be how /usr/bin/hostname handles file handles.

      It can be simplified to

      exec { '/bin/hostname': logoutput => true }
      

      This is getting into some core Ruby weirdness:

      ruby -e "Kernel.fork { \$stdout.reopen('/tmp/foo', 'w+'); Kernel.exec 'hostname' }"
      

      prints hostname to /tmp/foo when run from the command-line. When run as a systemd script:

      /usr/lib/systemd/system/print-hostname.service

      [Unit]
      Description=Print the hostname using Ruby
      Wants=basic.target
      After=basic.target network.target
       
      [Service]
      ExecStart=/usr/bin/ruby -e "Kernel.fork { $stdout.reopen('/tmp/foo', 'w'); Kernel.exec 'hostname' }"
      KillMode=process
       
      [Install]
      WantedBy=multi-user.target
      

      symlinked to /etc/systemd/system/multi-user.target.wants/print-hostname.service it creates an empty file.

      Changing the ruby script to

      foo = open('/tmp/foo', 'w'); pid = Kernel.fork { $stdout.reopen(foo); Kernel.exec 'hostname' }; Process.wait pid; foo.close
      

      to ensure the file is closed doesn't seem to change the behavior.

      Also, behavior is consistent with both system Ruby on Redhat 7 (2.0.0) and Ruby with a puppet-agent 1.6.2 build candidate.

      If I use a simple fork/exec without trying to redirect stdout, it prints correctly as a service and from the command-line. It's only once I redirect stdout that things get weird. The above is essentially what Puppet::Util::Execution.execute does, which is what the type is calling to. Interestingly, Facter::Core::Execution.execute (with Facter 3) works fine.

      With strace, I note that hostname calls write(1, ...) then immediately exits. Other examples will close fids 1 and 2 before exiting.

      Attachments

        Issue Links

          Activity

            People

              qa qa
              michael.smith Michael Smith
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Zendesk Support