Simple question, hopefully with a simple answer, but one I haven’t found yet:
How do I specify the shell options for JNLP agents?
Note: this is about which shell, but about how the shell is invoked. IE I want a full login shell, so that the agent picks up environment and shell variables in the regular places, just as a normal user would. It seems that this is not happening with the JNLP connectors.
Is there a Java argument I can set for the jnlp? Is there something I can add to my (declarative) pipelines?
the default I believe is /bin/bash? you can also add shebangs at the top of your sh() step, but i don’t think you’d want to do that every single case.
ex:
The setup for all of these things is kept in /etc/profile and in .bashrc, which of course only get loaded if the shell is interactive. I prefer to use these non-Jenkins-specific tools to create the build environment, because they are easily reproducible on developer environments.
However, reading the bash docs a bit more carefully, I see that there is a section on invoking non-interactive shells which states:
Invoked non-interactively
When Bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the filename.
So I think the answer can be summarised as follows:
sh is a well-defined step, don’t try to be cute with it.
if you want to get cute, try setting ${BASH_ENV} in the pipeline - at least you only have to set it once per pipeline.
if you want a customisable shell, write your own library for it
can you not do #!/bin/bash -l? I haven’t tried it but it seems like the proper solution.
you could also just do
sh('''
source /etc/profile
do thing1
do thing 2
do thing 3
```)
or use the jenkins tools() system so you don’t need to install things on your system images
you could also use docker images and not have to worry about versions at all
you could add env variables (like PATH) when you add manage the agent, then it won’t matter what shell your using.
There’s lots of decent solutions to the problem your having, without having to hack the solution your wanting.
Edit i can’t find alink for managing env variables, but i added a screenshot to this post
Yes! indeed this would have been ideal - but my controller didn’t like that. Setting the shell in the /configure page to /bin/bash -l gave an error. If the sh step could be modified to support this kind of thing, it would be great.
Some more considerations - good suggestions in general, but not good for us in particular:
This is not a good option, at least for us, because it makes it difficult to run steps “out-of-band”, and creates a “special” environment in CI that cannot be reproduced in the developer’s machine.
Indeed, we do have containers for the build environment. They include a modified version of the standard Jenkins startup script – starting Vault Agent for example and provisioning relevant secrets during execution.
However, instead of maintaining NxMx… individual containers, we maintain one which is tested for the matrix of tool combinations. This means there is one agent label to select, very easy to maintain pipelines.
The key ingredient is the SDK selection tool, not the SDK itself. This greatly reduces the overhead in maintenance of images, not to mention the sum size of images we have to store in the registry, makes it easy to test combinations and allows developers to experiment with new versions.
We indeed do that, but this is not sufficient to setup the execution environment. The setup scripts of nvm and sdk need to be executed themselves in order to work.
The one variable that does show promise however is ${BASH_ENV} which would force the inclusion of the setup scripts that would otherwise have been used automatically.
I’m out of ideas sorry. I think you can modify your startup scripts (.bashrc/.bash_profile/etc) to ignore if your a login shell or not.
That being said, I switched from a bunch of version management tools to asdf a couple years ago and never looked back. Not only does it support tons of different languages and frameworks via plugins, and .tool-versions in the project itself. But I believe the majority of it works just with a couple env variables
Note that not all distributions have bash in /bin/. The #! should work, but maybe you need /usr/bin/bash, or even #!/usr/bin/env bash to run whatever bash in first on $PATH
Also, you could just create a default Groovy library with a myshell function that wraps the shell step, passing in the right shebang and whatever else you need, so you only need to do it once.