I have a Jenkins pipeline in which I'm trying to run the following command to deploy a jar on the server.
steps{
sh 'nohup java -jar admin/target/*.jar'
}
The actual code I'm using is this one.
String deployApplication = "BUILD_ID=dontKillMe " + "nohup java -jar " + dir_name + "/target/*.jar &"
But I'm unable to do so as this command is getting silently ingored when running through Jenkins. But when I run the same command manually through the terminal it runs successfully. And I tried the pwd command using Jenkins, it also ran successfully.
I have tried the fixes suggested by different people like the "BUILD_ID=dontKillMe" and "JENKINS_NODE_COOKIE=dontKillMe" but it did not work for me.
String deployApplication = "BUILD_ID=dontKillMe " + "nohup java -jar admin/target/*.jar"
String deployApplication = "JENKINS_NODE_COOKIE=dontKillMe " + "nohup java -jar admin/target/*.jar"
I tried using the above method by saving it in a variable, but it did not work. Please suggest what is going wrong?
P.S. I'm also attaching the manual execution output. The file in which these commands are getting saved in commands.sh and the port I'm using is 8100. enter image description here
There can be a lot of reasons why the script may be failing at the server end when you are trying to deploy:
Make sure that you are in the intended directory and logged in as the intended user with right permission while trying to execute the script. Try to see if a tail on nohup.out gives you any lead on what could be wrong.
If you have the exact jar name and it is a single jar, can you try to keep the exact name in script? Also see whether there is another application or another instance of the same application occupying the port which is intended to be used (assuming the jar is a runnable jar similar to what you get for springboot based applications). Use netstat -tunlp | grep portnumber.
If no process is running, then it may be a firewall issue. Check if firewall rules are written properly to enable the port at the server end. You can simply disable the firewall temporarily and then check if the command is executed successfully. Use systemctl stop firewalld to stop the firewall.
Related
I have a small java web app (grails), deployed under tomcat 8, from which I would like to execute a script on the local server using sudo. On a regular debian/ubuntu server all I have to do is use visudo to allow the tomcat user to execute sudo without a password on that particular script, and everything works as expected. When I tried installing the same war file on the raspberry pi (model 3b+, raspbian 10 - buster), booting from an SD card, the execution of the script always fails with the error "sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges'.
In an effort to track down this issue I have written another small executable jar that performs the same function (i.e. attempts to launch the script using sudo). This test program works as expected when logged in interactively (bash) as both the 'pi' and 'tomcat8' users (I had to set a shell for the tomcat8 user to order to get an interactive login). I then used strace to try and diagnose the issue. All I could glean from that is that getuid() is returning 111 (tomcat8) when trying to launch sudo when running under the tomcat8 service, but will return 0 when running in bash.
I have also written a small c program that simply calls getuid() and prints the result. If I run it under the tomcat8 user interactively (i.e. sudo su tomcat8), it prints '111' when I run it without sudo, and '0' when I run it with sudo. When I try and launch this program from the web-app (using process builder) I get '111' when the command is run without sudo, but I get the 'effective uid is not 0 ...' error when the command is prefixed with sudo.
I have checked mount, and there are a number of mounts with the 'nosuid' attribute, but not the root '/' directory where /usr/bin is located, and /usr/bin/sudo looks to have the correct permissions:
pi#raspberrypi:~/dev $ ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 147560 Jan 13 2019 /usr/bin/sudo
In desperation I have tried a couple of other things to just see what effect they might have:
* Added the tomcat8 user to adm, sudo and other groups
* Attempted to remount the other mounts without the nosuid attribute, although I couldn't remount about 6 or so because the mounts where in use.
Neither of these appeared to have any effect.
So it seems to me that the tomcat8 user can use sudo when in bash, but not when running as a daemon. Can anyone give me some ideas as to what is going on here? Is there anyway to diagnose or trace how an effective uid is determined by the os?
Other things that may be significant:
I installed both openjdk-8-jdk and tomcat8 via apt, and even though raspbian uses systemd, tomcat8 is launched via an init.d script. Not sure if this is causing uid issues.
If it is the SD card having some mounts with the nosuid attribute causing the problem, why doesn't it fail when running interactively?
It turns out it was an issue with the way the daemon is started, probably due to changes in the way Debian 10 starts daemon processes. I removed the tomcat init.d script, and replaced it with a systemd unit file, and included the following properties:
[Service]
...
NoNewPrivileges=false
AmbientCapabilities=CAP_SETGID CAP_SETUID
SecureBits=keep-caps
This allows the daemon to actually call setUid(0) successfully.
I've been stuck two weeks trying to figure out how to run this at startup.
I use the following chain of commands on the terminal:
1. source ~/.bashrc
2. source ~/.tinyos.sh
3. java net.tinyos.tools.Listen -comm serial#/dev/ttyUSB0:telosb | python demo.py`
The third command uses java to listen to the serial port and pipes it to a python script which cleans, converts and uploads to mysql localhost.
This works fine on ssh terminal. But ive tried using nohup+update-rc.d, upstart, systemd, crontab to make it run on startup and it just wont work! When I reboot and check logs / database, its as if the command never happened. I need this to run like a daemon and continue running until shutdown.
Thanks a lot.
How are you trying to execute the program ? Are there are permission issues accessing / executing the script ?
Which version of debian are you running - look at upstart scripts if you are running Jesse+
I'd put those three lines in a bash script and use upstart scripts to trigger them on start. Another option is to use supervisord to make sure that your scripts run and restart if for any reason the program crashes.
The following process normally works for my startup scripts. However, when I introduce a command to execute a JAR file, it does not work. This script works while I am logged in. However, it does not work as a startup script.
In /etc/init.d I create a bash script (test.sh) with the following contents:
#!/bin/bash
pw=$(curl http://169.254.169.254/latest/meta-data/instance-id)
pwh=$(/usr/bin/java -jar PWH.jar $pw &)
echo $pwh > test.txt
Make script executable
In /etc/rc.local, I add the following line:
sh /etc/init.d/test.sh
Notes:
I make a reference to the script in /etc/rc.local, because this script needs to run last after all services have started.
Please do not ask me to change the process (i.e., create script in /etc/init.d/ and reference it from /etc/rc.local), because it works for my other startup scripts.
I have tried adding nohup in front of java command, and it still did not work.
Thanks
As written, there is insufficient information to say what is going wrong. There are too many possibilities to enumerate.
Try running those commands one at a time in an interactive shell. The java command is probably writing something to standard error, and that will give you some clues.
We have created a Play application in Java and are deploying it to a dev-environment virtual machine using Atlassian Bamboo's SSH task: cd path/to/application/directory && start "" play run. This goes to the proper location, launches a new console, and starts play: the server is started successfully and we can access the site with no issues.
The problem is that the deployment task in Bamboo never stops because it is still monitoring the console where play run was called -- in the Bamboo status, we are seeing things like Deploying for 7,565 minutes. We thought adding the start "" would fix that issue, but in Bamboo it is the same as just doing the play run. Also, when we need to redeploy, we must first stop the deployment in process, and manually relaunch it.
Two questions:
How can we start the server from Bamboo in such a way that the deployment plan finishes?
How can we stop/kill the previous server from Bamboo at the beginning of the next deployment?
Bamboo is pretty bad for background tasks. Had a similar problem, eventually, we wrote a bash script that was run in background.
start.sh &1> /dev/null &2 > /dev/null &
not at all familiar with WAMP stack or the play cli, but try running it as a powershell command, which should run in and exit immediately
powershell -command "& <your command here>"
or failing that
powershell -command "& start-job { <your command here>} "
For Windows you can run background tasks using Groovy script.
Groovy can execute an external program as an process:
"/bin/application.exe".execute()
And then you can check that application is running:
println "tasklist /fi \"imagename eq application.exe\"".execute().text
So I have the following problem: I have a web service running inside a Tomcat7 server on Linux. The web service however has to execute some commands (mostly file operations such as copy and mount). Copy I've replaced with java.nio, but I don't think that there is a replacement for mount.
So I'm trying to execute shell commands out of my Tomcat Java process. Unfortunately it doesn't execute my commands. I've implemented the execution of shell commands in Java before. So my code should be correct:
Process pr = Runtime.getRuntime().exec("mount -o loop -t iso9660 <myimage> <mymountpoint>");
pr.waitFor();
<myimage> and <mymountpoint> are absolute paths, so no issues there either.
I've debugged my commands and they are working when executed on the console.
I've tried sending other commands. Simple commands such as id and pwd are working!
I've tried using /bin/bash -c "<command>", which didn't work.
I've tried executing a shell script, which executes the command, which didn't work.
I've tried escaping the spaces in my command, which didn't work.
So I've digged even deeper and now I'm suspecting some Tomcat security policy (Sandbox?), which prevents me from executing the command. Since security is no issue for me (it's an internal system, completely isolated from the outside world), I've tried a hack, which became quite popular just recently:
System.setSecurityManager(null);
This didn't work either. I'm using Java7 and Tomcat7 on RHEL6. Tomcat7 is just extracted! I don't have any files in /etc/.. or any other folder than /opt/tomcat/, where I've extracted the zip from the Tomcat home page. I've searched the /opt/tomcat/conf folder for security settings, but all I could find was the file catalina.policy, where it didn't seem like I could set some security level for shell commands.
Any ideas?
A few things:
System.setSecurityManager(null);
you have just killed the security of your application.
Yes, Tomcat is running as root. If I execute id I'm root as well.
Fix this immediately!
Now on to the question. You shouldnt have Tomcat executing anything, you need to defer this to a separate process whether that be a shell script or another Java program. This should also remove what (I hope) was a dependency on root running Tomcat. It should be possible to perform this command as a non-privileged user that cannot log into the system normally. You would do this by configuring /etc/fstab and supplying that same user the permissions to do this. From a pure security POV the process that mounts should not be owned by the tomcat user. Nor should the tomcat user ever be root. So to recap:
1) Stop running Tomcat as root
2) Create a separate process outside of the context of Tomcat to run this mount
3) Create a tomcat user, this user should not be able to log into the system nor should it be a privileged user (admin,super user, etc)
4) Create a process user, this user should be configured exactly as the tomcat user
5) Edit /etc/fstab giving the process user the necessary permissions to mount correctly.
It's generally a bad idea to use the single-string form of Runtime.exec. A better option is to use ProcessBuilder, and split up the arguments yourself rather than relying on Java to split them for you (which it does very naïvely).
ProcessBuilder pb = new ProcessBuilder("/bin/mount", "-o", "loop", /*...*/);
pb.redirectErrorStream(true); // equivalent of 2>&1
Process p = pb.start();
You say you're on RHEL so do you have selinux active? Check your logs and see if this is what's blocking you (I think it's audit.log you're looking for, it's been a few years since I've used selinux). If this does turn out to be the problem then you should probably ask on superuser or serverfault rather than SO...
I'm not sure if that's the problem you are having, but I've seen issues when Runtime.exec() is used without reading the associated output buffers. You can find a detailed explanation and potential solutions here. Reading the output and error streams can also help you figure out what's going on at the OS level when you run the command.
I've recently had to do something like this from a Swing app.
You'll probably be able to pull it off with ProcessBuilder, as in Ian's answer, but I found that once things start to get complex, it's easier to write a shell script that does what you want, enabling you to pass as few parameters as possible. Then use ProcessBuilder to invoke the shell script.
If you're invoking anything that has more than really minimal output, you'll also have to read the output and error streams to keep the process from blocking when the output buffers fill, as it seems you are already doing.
I use sudo -S before command and for the tomcat7 user: tomcat7 ALL=(ALL) NOPASSWD:ALL