source /etc/profile

1,408 views
Skip to first unread message

Adrian

unread,
Dec 14, 2010, 12:42:12 PM12/14/10
to Puppet Users
Hello ,

There is a way to source /etc/profile inside puppet on demand?

My problem is that I install Java, afterwards I set JAVA_HOME variable
in /etc/profile.

After Java is installed, a gem which depends on Java starts to
install ... but as it needs JAVA_HOME environment to be set, it fails.

I am not sure what can I do ...

Thank you,

Adrian

Ken Barber

unread,
Dec 14, 2010, 6:29:50 PM12/14/10
to puppet...@googlegroups.com
Hi Adrian,

I'm not sure but I imagine by just trying to 'source' the profile within the current puppet runtime the scope will be lost as it would be called within an exec? 

Obviously if you are not worried about running puppet multiple times you might be able to source it in your 'prerun_command' script.

Otherwise I have one possible (albeit slightly hacky) option. Perhaps you can drop to ruby to ensure you set the variable JAVA_HOME within the puppet runtime. Let me give you an example I set-up on my machine:

/tmp/var.sh:

#!/bin/bash
echo $JAVA_HOME > /tmp/java_path

test.pp:

$dummy = inline_template("<% ENV['JAVA_HOME'] = '/opt/java_1.6.0_20' %>")
exec {"a":
        command => "/tmp/var.sh",
}
notice(inline_template("<%= ENV['JAVA_HOME'] %>"))

And to run it:

$ puppet test.pp 
notice: Scope(Class[main]): /opt/java_1.6.0_20
notice: /Stage[main]//Exec[a]/returns: executed successfully
$ cat /tmp/java_path
/opt/java_1.6.0_20

This shows that the environment variable is available at the scope when ruby does an exec (the exec resource) and when you try to grab the variable inline later on. Hopefully the gem provider should see this, but you'll have to make sure the inline_template runs before the gem does its work. Putting it in a class (like your "java" puppet class or something) and doing a require on the class may solve this.

Of course there is probably a nicer less complicated way of doing this :-).

ken.

Adrian Tofan

unread,
Dec 15, 2010, 8:08:47 AM12/15/10
to puppet...@googlegroups.com

Thank you for an interesting idea ,

> Hi Adrian,
>
> I'm not sure but I imagine by just trying to 'source' the profile within the current puppet runtime the scope will be lost as it would be called within an exec?
>
> Obviously if you are not worried about running puppet multiple times you might be able to source it in your 'prerun_command' script

I didn't manage to convince puppet to source the profile...

I've tried to add in [agent] section

prerun_command=/root/somecommand

but the command was not executed and I didn't see any log about it.

I wonder if

prerun_command = echo 'source /etc/profile'|/bin/bash

is suposed to work, because for the moment it is not.

Next, what I did is to send SIGUSR1 to puppet after updating /etc/profile with something like this

exec { "refresh_profile" :
command => "/usr/bin/killall -SIGUSR1 puppetd",
onlyif => "pidof -x puppetd",
path => "/bin:/usr/bin",
user => "root",
refreshonly => true,
}


> Otherwise I have one possible (albeit slightly hacky) option. Perhaps you can drop to ruby to ensure you set the variable JAVA_HOME within the puppet runtime. Let me give you an example I set-up on my machine:
> /tmp/var.sh:
> #!/bin/bash
> echo $JAVA_HOME > /tmp/java_path
> test.pp:
> $dummy = inline_template("<% ENV['JAVA_HOME'] = '/opt/java_1.6.0_20' %>")
> exec {"a":
> command => "/tmp/var.sh",
> }


My problem is that I do not use exec. What I do is something like this :

package { "buildr":
ensure => installed,
provider => "gem",
require => Package["sun-java5-jdk"],
}

When it tries to install the gem it needs the JAVA_HOME. Apparently if Java_HOME was set before running puppetd, then Java_Home is available to installer.

I am not sure what I can do next ...

> notice(inline_template("<%= ENV['JAVA_HOME'] %>"))
>
> And to run it:
>
> $ puppet test.pp
> notice: Scope(Class[main]): /opt/java_1.6.0_20
> notice: /Stage[main]//Exec[a]/returns: executed successfully
> $ cat /tmp/java_path
> /opt/java_1.6.0_20
> $
>
> This shows that the environment variable is available at the scope when ruby does an exec (the exec resource) and when you try to grab the variable inline later on. Hopefully the gem provider should see this, but you'll have to make sure the inline_template runs before the gem does its work. Putting it in a class (like your "java" puppet class or something) and doing a require on the class may solve this.
>
> Of course there is probably a nicer less complicated way of doing this :-).

This would be helpful - even if I don't totaly understand how it works - only if I can grab Java_Home from /etc/profile and assign it to

$dummy = inline_template("<% ENV['JAVA_HOME'] = 'JAVA_HOME_FROM_PROFILE' %>")


Felix Frank

unread,
Dec 15, 2010, 9:45:57 AM12/15/10
to puppet...@googlegroups.com
> Next, what I did is to send SIGUSR1 to puppet after updating /etc/profile with something like this
>
> exec { "refresh_profile" :
> command => "/usr/bin/killall -SIGUSR1 puppetd",
> onlyif => "pidof -x puppetd",
> path => "/bin:/usr/bin",
> user => "root",
> refreshonly => true,
> }

No good. Signaling puppet won't initialize your environment anew. You
would have to make the shell that runs puppetd source the profile, then
probably start puppet from scratch. Note that puppetd can be started by
init and not run in a shell at all.

Using puppet to initialize its own environment is tricky business at
best. As such, I found Ken's approach quite interesting.

Regards,
Felix

Richard Crowley

unread,
Dec 15, 2010, 11:07:06 AM12/15/10
to puppet...@googlegroups.com

Make a fake new puppetd that does what you want:

$ cat /usr/local/bin/puppetd
#!/bin/sh
set -e

export JAVA_HOME=whatever
# OR
. /etc/profile

exec /usr/bin/puppetd "$@"

Adrian Tofan

unread,
Dec 15, 2010, 1:01:29 PM12/15/10
to puppet...@googlegroups.com
Here is what I managed to do:

I was forced to replace package {"buildr":ensure=>installed....} with :

$java_home = "/usr/lib/jvm/java-1.5.0-sun"

exec { install_buildr:
command => "echo 'export JAVA_HOME=$java_home;gem install -y buildr'|/bin/bash",
path => "/usr/local/bin:/usr/bin:/usr/sbin:/bin",


require => Package["sun-java5-jdk"],

unless => "gem list buildr|grep buildr"
}

1. it may be possible to initialize $java_home from /etc/profile but I guess that is not that important
2. I am not sure how it will handle errors as the commands are piped to bash

Thank you all for the suggestions.

Jonathan Barber

unread,
Dec 16, 2010, 10:37:26 AM12/16/10
to puppet...@googlegroups.com
On 15 December 2010 18:01, Adrian Tofan <tofan....@gmail.com> wrote:
> Here is what I managed to do:
>
> I was forced to replace package {"buildr":ensure=>installed....} with :
>
>    $java_home = "/usr/lib/jvm/java-1.5.0-sun"
>
>    exec { install_buildr:
>        command => "echo 'export JAVA_HOME=$java_home;gem install -y buildr'|/bin/bash",
>        path => "/usr/local/bin:/usr/bin:/usr/sbin:/bin",
>        require => Package["sun-java5-jdk"],
>        unless => "gem list buildr|grep buildr"
>    }
>
> 1. it may be possible to initialize $java_home  from /etc/profile but I guess that is not that important

If you're going to specifically execute bash, it might be cleaner to
spawn it as a login shell and actually get the profile sourcing (the
INVOCATION section of the bash man page).

There's also the "environment" parameter for the exec resource as
well, which means you specifically set up the environment and not have
do the bash trick.

Finally, I've been using the gem "query" command to report on installed gems:
define install-gem ($version = '') {
exec { "gem $name $version":
path => "${thirdparty::cwd}/jruby-1.5.5/bin:/bin:/usr/bin",
environment => "GEM_HOME=$path",
command => "jruby -S gem install $name --version $version
--install-dir $path --config-file $cfg",
unless => "jruby -S gem query -i --name-matches $name --version
$version --config-file $cfg",
require => [ Class[jruby], File[$path], File[$cfg] ],
}
}

It's nice because it returns success/failure and so doesn't require the grep.

> 2. I am not sure how it will handle errors as the commands are piped to bash

Bash will return the exit status of the last command:
[x01024@addict rpmbuild]$ echo "true; false" | bash
[x01024@addict rpmbuild]$ echo $?
1
[x01024@addict rpmbuild]$ echo "false; true" | bash
[x01024@addict rpmbuild]$ echo $?
0

> Thank you all for the suggestions.

--
Jonathan Barber <jonatha...@gmail.com>

Jonathan Barber

unread,
Dec 16, 2010, 10:44:46 AM12/16/10
to puppet...@googlegroups.com
On 15 December 2010 13:08, Adrian Tofan <tofan....@gmail.com> wrote:
>
> Thank you for an interesting idea ,
>
>> Hi Adrian,
>>
>> I'm not sure but I imagine by just trying to 'source' the profile within the current puppet runtime the scope will be lost as it would be called within an exec?
>>
>> Obviously if you are not worried about running puppet multiple times you might be able to source it in your 'prerun_command' script
>
> I didn't manage to convince puppet to source the profile...
>
> I've tried to add in [agent] section
>
> prerun_command=/root/somecommand
>
> but the command was not executed and I didn't see any log about it.

According to the source (0.25.5), prerun commands are executed in
child processes, so when the child exits, their environment is lost.

Regards
--
Jonathan Barber <jonatha...@gmail.com>

Reply all
Reply to author
Forward
0 new messages