5

My Jenkins runs inside Tomcat which runs under user buildman, therefore all the jobs run under that user (in CentOS). Some of my jobs depend on environment variables, which I set in .bashrc. However, the Jenkins jobs do not see any of the variables set in that file even though that script is supposed to be sourced for non-login shells, such as what I would think Jenkins should be (?).

The workaround is simple: I just copy and paste all the variables from my .bashrc into the build command script in Jenkins. But that is not very elegant. Is there any way to get Jenkins to source the .bashrc of the user it runs under so that it gets its usual configuration without having to set it separately in each job?

amphibient
  • 29,770
  • 54
  • 146
  • 240
  • `.bashrc` is sourced by *interactive* shells, not non-interactive shells. – chepner Mar 17 '17 at 22:19
  • sorry, i meant non-login shell – amphibient Mar 17 '17 at 22:30
  • is Jenkins a non-interactive shell ? – amphibient Mar 17 '17 at 22:32
  • Is there a reason you're copying-and-pasting rather than just making the operation explicit (`. ~/.bashrc`) when you need it? Or, better, having a separate configuration file you source *both* from `~/.bashrc` *and* from your scripts, so you don't need to worry about configuration tweaks meant for interactive use messing up your scripts? – Charles Duffy Mar 17 '17 at 22:34
  • and, err, yes, an "interactive" shell is by convention one with a TTY attached at which a human with a keyboard is issuing commands. That's not what you have with Jenkins. (...now, in terms of "which dotfiles get invoked?", then you have the question of whether `-i` was passed as an argument to the shell at invocation time, but telling the shell to behave as if it were being operated by a human with a keyboard when it's not, while technically possible, is by no means good form). – Charles Duffy Mar 17 '17 at 22:36
  • frankly, `.bashrc` is the wrong place to set environment variables even for an interactive shell -- `.bash_profile` is more appropriate for that purpose, since (in a traditionally-configured environment, which not all are) it gets run only *once* per login session. (Environment variables by definition are inherited from their parent process -- that's what distinguishes them from regular shell variables -- so there's no point to setting them over and over; hence, having them be set only for your *login shell*, and not on every *interactive shell* that follows). – Charles Duffy Mar 17 '17 at 22:38
  • i had it in `.bash_profile` but i moved it to `.bashrc` hoping it would become accessible to Jenkins there. yes, i can just source whatever script it is in in the Jenkins command but i was looking for a way to not even have to do that – amphibient Mar 17 '17 at 22:40
  • If something is truly global to every job you'd ever want to run, you could have those variables set before Tomcat even starts -- as aforementioned, environment variables are inherited by subprocesses (unless something is explicitly going out of its way to clear them), so if you set them for the process that's starting Tomcat, they get inherited by Tomcat -> inherited by the process running Jenkins -> inherited by your child shell -> and there you are. Unless Jenkins is clearing them. Which is possible, I suppose, but would be easy to pick up on. – Charles Duffy Mar 17 '17 at 22:41
  • ...but anyhow, exactly *how* you're starting Tomcat matters. If it's via a systemd service, then you'd define your environment variables in the service definition or an `EnvironmentFile` it reads, etc. – Charles Duffy Mar 17 '17 at 22:43
  • (and, well, yes, you can cheat and run your shell with `-l` or `-i` flags, but that has unintended and sometimes unpleasant side effects; there are interactive facilities that are better off disabled in scripts that are present by default in shells run with `-i`). – Charles Duffy Mar 17 '17 at 22:44
  • 1
    Personally, though, I'd not have a shell involved at all, and use the [EnvInject Plugin](https://wiki.jenkins-ci.org/display/JENKINS/EnvInject+Plugin). That way, a dump of your Jenkins configuration is complete enough to include everything needed to actually run your jobs, and you're having one fewer place where code is being executed without folks thinking hard about it (and without it being tracked in version control etc). – Charles Duffy Mar 17 '17 at 22:48
  • I like that idea – amphibient Mar 17 '17 at 22:55
  • 1
    You can also set environment variable key-value pairs globally (in the Jenkins global config), or per node. – Christopher Orr Mar 21 '17 at 10:43

4 Answers4

6

Jenkins creates a temporary sh-script for each script section (at least when using a "classical" project - for the Pipeline approach I'm not sure). This temporary script is executed with sh. On most Linux systems this is a symlink to bash, this SO-post gives some insights.
Also according to the man-pages of bash invoking bash with sh "tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well." This means the .bashrc is not interpreted at all. However you can try to source the bashrc for each shell-invocation...

Community
  • 1
  • 1
L. Tischler
  • 344
  • 1
  • 5
0

So, I tried a few things and the only solutions that seems to work are:

  • have a shell script in your repo that uses bash
  • write a file, chmod it via sh and then run it

In both case, there needs to be an executable file with content like:

#!/usr/bin/env bash
...

Using sh """ bash -c "...." """" doesn't seem to work

Peter Kahn
  • 12,364
  • 20
  • 77
  • 135
0

When my Jenkins agent launches by SSH on redhat linux, I see it does print environment variables defined in .bashrc.

My problem with not seeing changes to .bashrc was because I needed to relaunch the agent, so it picked up the change.

Carl Walsh
  • 6,100
  • 2
  • 46
  • 50
-1

I have found a command that works for me

In .profile, .bashrc, etc.:

export MY_BASH_VAR=123

In Execute Shell:

VAR=$(bash -c "source ~/.profile && echo \$MY_BASH_VAR")
echo $VAR

Will print 123 in the output console when the job builds

Jon
  • 31
  • 1
  • 5
  • yes but in this case each job that concerns the variabls in .profile will have to include this script. A better solution could be to launch agent with pre-loaded .profile or similar. I dont know if that is even possible. – Muhammad Faizan-Ul-Haq May 26 '21 at 07:33