How to include 3 commands into 1 java class - java

please advice in following problem.
there is UNIX server.
I have 3 separate commands which I can do in UNIX server:
1. java com.documentum.server.impl.utils.TestConnection SERVER_NAME PORT_NUMBER do_method
2. dmqdocbroker -t SERVER_NAME -p PORT_NUMBER -c getserver
3. dmqdocbroker -t SERVER_NAME -p PORT_NUMBER -c getservermap <REPOSITORY_NAME>
Note:
dmqdocbroker - shell script.
I want to include 3 commands into one java class and each command's output to be written
to separate log file. But i don't know how to implement it.
Also, could you please advice how it can be checked in eclipse?
Please advice.
With regards!

Based on the other answers, here's what a shell implementation would look like:
#!/bin/sh
java com.documentum.server.impl.utils.TestConnection SERVER_NAME PORT_NUMBER do_method &> log_file_1
dmqdocbroker -t SERVER_NAME -p PORT_NUMBER -c getserver &> log_file_2
dmqdocbroker -t SERVER_NAME -p PORT_NUMBER -c getservermap <REPOSITORY_NAME> &> log_file_3
If you're curious, the command &> filename means that you're putting both standard output and error output to the same log file. If you want those to go to different log files, you can do any combination of > fileA for standard output and 2> fileB for standard error.
Finally, if you want to have those three commands happen simultaneously, you can put a bare & at the very end.

Take a look in api of Process and Runtime.exec. In Process, you can use getInputStream() and getErrorStream() to get the stdout and stderr of the process and do your redirection.
However, it does not make sense to me to write a java program for such purpose. Writing a shell script will be much simpler.

Related

Prevent application (iscsiadm) logging to dmesg?

I have an issue where running sudo iscsiadm -m discovery -t st -p IP -l logs to dmesg across all terminals on the server.
The command is run from a java application, using:
Runtime.getRuntime().exec("/bin/bash", "-c", "sudo iscsiadm -m discovery -t st -p *IP* -l");
I have tried the following:
Apppending > /dev/null 2>&1 to the end of the iscsiadm discovery... command
Capturing input streams from the returned progress (process.getInputStream() and process.getErrorStream())
Appending > /dev/null 2>&1 to the software launching the Jar.
None of the above attempts prevent logging across all virtual terminals. The log starts [some_num.some_dec] LOG_MESSAGE which suggests it is outputting to dmesg? If this is true how do I prevent this? Currently it makes the system impossible to debug because it's printing over the terminal prompt.
Thanks
Issue fixed.
It turns out it was not iscsiadm logging to dmesg, it was the mount command afterwards because the blockdev did not exist.
I have modified my java code to try iscsiadm -m discovery... then run iscsiadm -m session to determine if the appropriate device has a connection or not prior to mounting.

How to run sudo command for OS X in java

I am working on app in javafx , I am trying open an application using a command in terminal, I am running the command using my java code my command have some variable it's have path of my installer file which will not always be same because file name can be different as the builds are updated.
here is a sample as how I am running the command it's not the exact command which I am running but the command format is same.
Process process = Runtime.getRuntime().exec("echo password | sudo -S open -a safari");
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
The process is not giving any output it stops there and nothing happens.
The same command I have tried from terminal and it works fine.
I have tried the things mention in this link
How to execute bash command with sudo privileges in Java?
but it also didn't worked.
I am also running command like "chmod +x" from my java code these commands runs fine.
my original command looks like this:-
runCommand = "echo" + " " + password + "| sudo -S " + "\"" + a.getAbsolutePath() + "\"" + " --deploymentFile="
+ "\"" + b.getAbsolutePath() + "\"";
where a.getAbsolutePath() is the path of the installer file and b.getAbsolutePath() is the path of the deployment file we used to install the application.
pb.getInputStream()
prints the command and when I copy and paste it is terminal it's runs fine.
pb.getErrorStream()
doesn't give anything.
I have tried running
String[] cmd = {"/bin/bash","-c","echo tester| sudo -S ","\"",a.getAbsolutePath(),"\"","\""," --deploymentFile=","\"",b.getAbsolutePath()};
and
String[] cmd = {"/bin/bash","-c","echo tester| sudo -S",a.getAbsolutePath(),"--deploymentFile=","\"",b.getAbsolutePath()};
also
here I got following error
getErrorStreamusage: sudo -h | -K | -k | -L | -V
getErrorStreamusage: sudo -v [-AknS] [-g groupname|#gid] [-p prompt] [-u user name|#uid]
getErrorStreamusage: sudo -l[l] [-AknS] [-g groupname|#gid] [-p prompt] [-U user name] [-u
getErrorStream user name|#uid] [-g groupname|#gid] [command]
getErrorStreamusage: sudo [-AbEHknPS] [-C fd] [-g groupname|#gid] [-p prompt] [-u user
getErrorStream name|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] [<command>]
getErrorStreamusage: sudo -e [-AknS] [-C fd] [-g groupname|#gid] [-p prompt] [-u user
getErrorStream name|#uid] file ...
sudo
I'd strongly suggest to edit the sudoers file and allow the user running the application to use the specific commands via sudo without prompting for a password instead of doing an echo passwd | sudo ... construction.
That way you avoid storing passwords in the clear (or at best slightly obfuscated) in an application or configuration file, and you avoid the need to call a shell with a shell script that calls sudo, etc.
Sudoers can be edited via the command visudo. See here as an example how it is done on unbuntu, but it's the same on any unix. https://askubuntu.com/questions/159007/how-do-i-run-specific-sudo-commands-without-a-password
Additional ref: https://www.sudo.ws/man/1.8.16/sudoers.man.html
I think you're asking the wrong question though...
Authorization on a mac
On a mac applications that need to perform operations that require additional rights are not supposed to use sudo to start with.
An app is supposed to use the authorization services instead.
References:
Introduction to Authorization Services Programming Guide (apple)
Authorization Services Tasks (apple)
I need to give a java application super user access to view protected files on a mac
Is there any graphical "sudo" for Mac OS X?
I think you must use the full path to the application. This should work:
Runtime rt = Runtime.getRuntime();
rt.exec("echo password | sudo -S open -a /Applications/Safari.app");
Update:
Based on your comment you could try to split the process. The chances are good that open needs an interactive session.
Create a script (e.g. openSafari.sh) that will open Safari as user.
#!/etc/bash
echo $1 | sudo -S open -a /Applications/Safari.app &
Make it executable: chmod +x openSafari.sh, and call that script from java.
Runtime rt = Runtime.getRuntime();
rt.exec("/pathTo/openSafari.sh 'sudoPassword'");
I would NOT recommend doing this - do not shout at me if you break something :)
But what you are asking for can be achieve with:
String[] cmd = {"/bin/bash","-c","echo password | sudo -S open -a <path to app>"};
Process pb = Runtime.getRuntime().exec(cmd);
The Runtime.exec() methods run the given command directly, not via a shell. The particular overload you are using tokenizes the command at whitespace, and interprets the resulting tokens as the name of the command and the arguments. The only command executed by your invocation ...
Runtime.getRuntime().exec("echo password | sudo -S open -a safari");
... is therefore echo; everything else is an argument. The result is the following output to the process's standard output:
password | sudo -S open -a safari
There are at least a couple of ways to accomplish what you appear to want. The simplest modification of your original code would probably be
Process process = Runtime.getRuntime().exec(
new String[] { "bash", "-c", "echo password | sudo -S open -a safari" });
That achieves what you thought you were getting, by explicitly invoking a shell to run the command.
But that's a substantial security risk, because the password will appear in plain text in the process list. You can instead have your Java program feed in the password directly, and then also avoid getting bash involved:
Process process = Runtime.getRuntime().exec("/usr/bin/sudo -S open -a safari");
Writer toSudo = new OutputStreamWriter(process.getOutputStream());
String password = "password";
toSudo.write(password);
toSudo.write('\n'); // sudo's docs demand a newline after the password
toSudo.close(); // but closing the stream might be sufficient
Other considerations:
It is wise to give a full path to the sudo command, as demonstrated, to avoid running a different sudo that happens to be found first in the path. Since you're going to give it the password to a privileged account, it is important to minimize the possibility of running a rogue program.
It would also be wise to avoid storing passwords in the program or in a configuration file; thus, solutions that involve feeding a password to sudo should also involve inputting the password interactively from a user.
Security-conscious Java programs often prefer to keep passwords in char arrays instead of in Strings, so that they can be proactively wiped when no longer needed. Strings cannot be changed, and they may hang around inside the VM indefinitely (even more so than many other objects).
Generally speaking, you need to drain a Process's input and error streams, concurrently, whether you do anything with the contents or not. If you do not do so then the external process may block and / or may fail to exit. That's probably not an issue with safari in particular, however, because I don't think it ordinarily produces any output on those streams.
maybe use this
How to setup a SUDO_ASKPASS environment variable?
You can set the SUDO_PROMPT enviroment variable within the process call
Combine that with the fix to how you're using process jon bollinger, maciej, etc have mentioned.
Then have that bring up a password prompt for your user, or access a pki with your credentials in it. (for the love of god at least aes encrypt it if you go for the pki)
as you've said this is meant to run on others machines, it'll basically be a shitty uac prompt and that doesn't sound like a very mac/linux solution. swa66 is the best way, but this'll do quick and dirty.

How to run a script in user mode inside an executable jar that is executed as root?

I want to run the following script within a Java executable jar on the Raspberry Pi.
the script (= stream.sh):
#!/bin/sh
raspivid -fps 25 -w 640 -h 360 -vf -n -o - -t 999999 |cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/cam.sdp,rtcp-mux}' :demux=h264
the Java code:
Runtime.getRuntime().exec("sh stream.sh"));
The problem is that the jar must be run with sudo and the vlc command doesn't accept sudo. Neither the script or the Java code contain sudo but as the jar is executed as sudo, vlc still gives the error "VLC is not supposed to be run as root...".
What is the easiest way to make the script run in user mode inside the jar?
I would use su -l $LOGIN -c $CMD or sudo -u $LOGIN $CMD.
Runtime.getRuntime().exec("sudo -u myuser sh stream.sh"));
man sudoers has all the information you need.
You need to change /etc/sudoers

How to get exit status, standard output and standard error streams of Java application in shell script?

My shell script needs to get the result (exit status) and capture the log output from Java application, which writes to its standard output and standard error streas.
To get the status code of the Java application I can do this:
RESULT=$(java <My app>)
To get its output streams I can do this:
$java <My app> >> Mylog.txt 2>&1 || true;
But I can't find a way to get both.
The exit status of the most recently run program is available in the variable $?. Hence, you can do this:
$java <My app> >> Mylog.txt 2>&1
RESULT=$?
Best solution in standard unix way is to redirect stderr and/or stdout file descriptors:
Redirect stderr before your invokation, capture result and as soon as possible restore this:
Example:
#!/bin/bash
...
#Modify sdterr file descriptor
exec 6<&2
exec 2>$LOG_STDERR
#Your Java Invokation
$("here invoke your java")
$RESULT = $?
#Restore sdterr file descriptor
exec 2<&6 6<&-
You can use the tee command to both append your output and keep writing to stdout:
RESULT_STDOUT=$($java classname | tee -a Mylog.txt)
Here, the -a asks tee to append to Mylog.txt, if possible.
I'm not sure why you need the true there, so I excluded that. The main problem here is how to preserve the error log. If you do 2>&1 it will become part of Mylog.txt but also of the result. If storing the error log in a separate file is sufficient for you, you can redirect it with
RESULT_STDOUT=$($java classname 2>> Mylog.error.txt | tee -a Mylog.txt)
EDIT:
The exit status you can get via $PIPESTATUS, as #Raedwald pointed out: Pipe output and capture exit status in Bash. The above solution captures stdout as RESULT_STDOUT only.

How to create a script to restart a JAR file and get output in a terminal?

I have used the following scripting for start and stop a jar file.
**start.sh**
#!/bin/bash
nohup nice java -jar Server.jar > ./Server.out 2>&1 &
**stop.sh**
#!/bin/bash
kill `ps -ef | grep Server.jar | grep -v grep | awk '{ print $2 }'`
Now I want to merge both scripts and create a new restart script. I also want this script output in a terminal instead of a text file(Server.out).
Would appreciate any kind of input/help.
You can either put the commands of the two sripts after each other (kill first, java second) or just call the two scipts in the appropriate order.
The idea is that restart is basically equivalent to killing the current running version and starting a new one.
To avoid the output to a file, remove the > ./Server.out part.
Edit: removed note about removing the redirection part as I misread the grep part of the kill script
Update: Missed the nohup part of the script: with nohup you need to redirect output to a file, because the process is detached from the terminal (see documentation). If you do want to see the output in the terminal, remove nohup as well as the redirection to the file

Categories