How to run jar through jenkins as a separate process? - jenkins

The question is this: I need to run a jar file on the node, in the Jenkins pipeline I write
stage('Start bot') {
steps {
sh 'nohup java -jar /home/oomnpe/workspace/oomnpe_bot/target/oomnpe_bot-1.0-jar-with-dependencies.jar'
}
}
But the build goes on endlessly after launching the jar, showing the logs of the application, if you make requests to it. If I stop the build, then the application also stops.
How to make the jar run on the remote machine and the build stop? Everywhere they write about "nohup", but I use it and there is no result.

Try the following. Check this issue for more details.
withEnv(['JENKINS_NODE_COOKIE=dontkill']) {
sh "nohup java -jar /home/oomnpe/workspace/oomnpe_bot/target/oomnpe_bot-1.0-jar-with-dependencies.jar &"
}

Related

Can I speed up Gradle daemon startup on Jenkins CI?

Every time I push my gradle build to Jenkins, it spends a considerable amount of time on this step:
Starting a Gradle Daemon (subsequent builds will be faster)
The relevant part of my Jenkinsfile looks like this:
stage('Build') {
steps {
withGradle() {
sh 'chmod +x gradlew'
sh './gradlew build jar'
}
}
}
I assumed withGradle() would try to persistently run a gradle daemon in the background on Jenkins to avoid this sort of thing, but at this point i'm not entirely sure it does anything - the docs for it are incredibly vague.
How do I improve build times with this system?
withGradle is contributed by Jenkins' Gradle Plugin and contributes console output highlighting and build scan URL capturing (showing the build scan URL in the Jenkins UI). It certainly doesn't do anything with the Gradle daemon. You do not need withGradle to run you Gradle builds in Jenkins, depending whether you use build scans of course. Doing just
stage('Build') {
steps {
sh 'chmod +x gradlew'
sh './gradlew build jar'
}
}
is perfectly fine.
Gradle daemons stop themselves after being idle for 3 hours (FAQ). If a build runs just once a day the daemon will be dead for sure. This is usually the reason why the daemon is absent and needs to be started.
Gradle might also decide to start a new daemon instance if the running daemon is classified incompatible (build environment, e.g. heap memory settings, changed). This is explicitly highlighted in the build output according to my information.
With regards to slow daemon startup performance, the usual advice to run the build on the latest Gradle and Java versions.
One last tip though. Should you be using Git as version control system, you can get rid of the sh 'chmod +x gradlew' by letting Git setting the executable flag via update-index:
git update-index --chmod=+x gradlew

jenkins pipeline. Ssh to a server get stuck on job

I need to ssh to a server from a simple jenkin pipeline and make a deploy which is simply moving to a directory and do a git fetch and some other comands (nmp install among others). Thing is that when jenkin job ssh to the remote server it connects ok but then It gets stucked, I have to stop it. I just now modify the script to simply do a "ssh to server " and a "pwd command" to go to the easiest but it connects to it and it get stuck untill I abort. What Am I missing? here is the simpe pipeline script and the output on an screenshot
pipeline {
agent any
stages {
stage('Connect to server') {
steps {
sh "ssh -t -t jenkins#10.x.x.xx"
sh "pwd"
}
}
stage('branch status') {
steps {
sh "git status"
}
}
}
}
Jenkins executes each "sh" step as a separate shell script. Content is written to a temporary file on Jenkins node and only then executed. Each command is executed in separate session and is not aware of previous one. So neither ssh session or changes in environment variable will persist between the two.
More importantly though, you are forcing pseudo-terminal allocation with -t flag. This is pretty much opposite to what you want to achieve, i.e. run shell commands non-interactively. Simply
sh "ssh jenkins#10.x.x.xx pwd"
is enough for your example to work. Placing the commands on separate lines would not work with regular shell script, regardless of Jenkins. However you still need to have private key available on node, otherwise the job will hang, waiting for you to provide password interactively. Normally, you will want to use SSH Agent Plugin to provide private key at runtime.
script {
sshagent(["your-ssh-credentals"]) {
sh "..."
}
}
For execution on longer commands see What is the cleanest way to ssh and run multiple commands in Bash?

How to run a docker-compose instance in jenkins pipeline

I've set up a home based CI server for working with a personal project. Below you can see what happens for the branch "staging". It works fine, however the problems with such a pipeline config are:
1) The only way to stop the instance seem to be to abort the build in jenkins whiсh leads to the exit code 143 and build marked as red instead of green
2) If the machine reboots I have to trigger build manually
3) I suppose there should be a better way of handling this?
Thanks
stage('Staging') {
when {
branch 'staging'
}
environment {
NODE_ENV = 'production'
}
steps {
sh 'docker-compose -f docker-compose/staging.yml build'
sh 'docker-compose -f docker-compose/staging.yml up --abort-on-container-exit'
}
post {
always {
sh 'docker-compose -f docker-compose/staging.yml rm -f -s'
sh 'docker-compose -f docker-compose/staging.yml down --rmi local --remove-orphans'
}
}
}
So, what's the goal here? Are you trying to deploy to staging? If so, what do you mean by that? If jenkins is to launch a long running process (say a docker container running a webserver) then the shell command line must be able to start and then have its exit status tell jenkins pipeline if the start was successful.
One option is to wrap the docker compose in a script that executes, checks and exits with the appropriate exit code. Another is to use yet another automation tool to help (e.g. ansible)
The first question remains, what are you trying to get jenkins to do and how on the commandline will that work. If you can model the command line then you can encapsulate in a script file and have jenkins start it.
Jenkins pipeline code looks like groovy and is much like groovy. This can make us believe that adding complex logic to the pipeline is a good idea, but this turns jenkins into our IDE and that's hard to debug and a trap into which I've fallen several times.
A somewhat easier approach is to have some other tool allow you to easily test on the commandline and then have jenkins build the environment in which to run that command line process. Jenkins handles what it is good at:
scheduling jobs
determining on which nodes jobs run
running steps in parallel
making the output pretty or easily understood by we carbon based life forms.
I am using parallel stages.
Here is a minimum example:
pipeline {
agent any
options {
parallelsAlwaysFailFast() // https://stackoverflow.com/q/54698697/4480139
}
stages {
stage('Parallel') {
parallel {
stage('docker-compose up') {
steps {
sh 'docker-compose up'
}
}
stage('test') {
steps {
sh 'sleep 10'
sh 'docker-compose down --remove-orphans'
}
}
}
}
}
post {
always {
sh 'docker-compose down --remove-orphans'
}
}
}

Execute a script from jenkins pipeline

I have a jenkins pipeline that builds a java artifact,
copies it to a directory and then attempts to execute a external script.
I am using this syntax within the pipeline script to execute the external script
dir('/opt/script-directory') {
sh './run.sh'
}
The script is just a simple docker build script, but the build will fail
with this exception:
java.io.IOException: Failed to mkdirs: /opt/script-directory#tmp/durable-ae56483c
The error is confusing because the script does not create any directories. It is just building a docker image and placing the freshly built java artifact in that image.
If I create a different job in jenkins that executes the external script as
its only build step and then call that job from my pipeline script using this syntax:
build 'docker test build'
everything works fine, the script executes within the other job and the pipeline
continues as expected.
Is this the only way to execute a script that is external to the workspace?
What am I doing wrong with my attempt at executing the script from within
the pipeline script?
The issue is that the jenkins user (or whatever the user is that runs the Jenkins slave process) does not have write permission on /opt and the sh step wants to create the script-directory#tmp/durable-ae56483c sub-directory there.
Either remove the dir block and use the absolute path to the script:
sh '/opt/script-directory/run.sh'
or give write permission to jenkins user to folder /opt (not preferred for security reasons)
Looks like a bug in Jenkins, durable directories are meant to store recovery information e.g. before executing an external script using sh.
For now all you can do is make sure that /opt/script-directory has +r +w and +x set for jenkins user.
Another workaround would be not to change the current directory, just execute sh with it:
sh '/opt/script-directory/run.sh'
I had a similar concern when trying to execute a script in a Jenkins pipeline using a Jenkinsfile.
I was trying to run a script restart_rb.sh with sudo.
To run it I specified the present working directory ($PWD):
sh 'sudo sh $PWD/restart_rb.sh'

Why won't groovy run in Jenkins pipeline?

I am currently trying to run a groovy script from my pipeline as one of my nodes, but I ran into this error:
[CompanyName] Running shell script
+ ./ideainspect.groovy
env: groovy: No such file or directory
Also, I tried installing the plugin for groovy, but for some reason, it won't install. Whenever I refresh the page for tools, the installer goes away. Am I installing groovy wrong? Please help!
Edit: Relevant Data
stage 'Static Analysis'
node {
dir("Android/btMobileApp") {
sh "./ideainspect.groovy"
sh "./gradlew checkstyle lintDebug"
}
}
And the ideainspect.groovy file is an executable with the shebang #!/usr/bin/env groovy, which could be the problem.
Does your jenkins user have groovy on its path? If so ditch the shebang and try
sh 'groovy ideainspect.groovy'
If it's not on the path, you can try
sh '/usr/bin/groovy ideainspect.groovy'
(or wherever groovy is installed)
Or alternatively add it to the path environment variable using Manage Jenkins -> Configure Systems. This may not be appropriate if you have lots of projects using different versions of groovy

Resources