Running bash cmds within Java [duplicate] - java

This question already has answers here:
Java Runtime Exec With White Spaces On Path Name
(2 answers)
Closed 5 months ago.
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
I'm trying to run a bash cmd that grabs infomation from the google api using my api key. I run the code in the terminal and I get the output that I want (which is the address alone). But when I try use the call within java it doesnt work. I believe it ends up being a null call.
The cmd is as follows:
"wget -O- -q "https://maps.google.com/maps/api/geocode/json?address=4-chōme-2-8 Shibakōen, Minato City, Tokyo 105-0011, Japan&key=[MY_API_KEY]"|grep '"formatted_address"'|cut -d\: -f2
This is my current java code
public static void main(String[] args) throws Exception {
Process runtime = Runtime.getRuntime().exec("wget -O- -q \"https://maps.google.com/maps/api/geocode/json?address=4-chōme-2-8 Shibakōen, Minato City, Tokyo 105-0011, Japan&key=[MY_API_KEY]\"|grep '\"formatted_address\"'|cut -d\\: -f2");
Show_Output(runtime);
}
public static void Show_Output(Process process) throws IOException {
BufferedReader output_reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String output = "";
while ((output = output_reader.readLine()) != null) {
System.out.println(output);
}
System.out.println(output);
}
Desired output is:
"4-chōme-2-8 Shibakōen, Minato City, Tokyo 105-0011, Japan",

With the Process class you can only execute a single command. You on the other hand have 3:
wget -O- -q "https://maps.google.com/maps/api/geocode/json?address=4-chōme-2-8 Shibakōen, Minato City, Tokyo 105-0011, Japan&key=[MY_API_KEY]"
grep '"formatted_address"'
cut -d: -f2
I see 4 options:
create a shell script that contains these commands, and execute that
create 3 processes (one for each command), and chain their input / output streams.
use a process only for the curl command, and perform the grep and cut in Java
skip using commands completely, and just use Java for the entire thing
I'd personally go for option 4. With Java's own HttpClient this should be pretty straight forward.
use HttpClient to get the response as a string
use response.lines() to get a stream of lines
use filter to replace grep (.filter(line -> line.contains("...")))
use string manipulation to replace cut

Related

Java - how can i type in user input using cmd command [duplicate]

This question already has answers here:
How to get input via command line in Java? [closed]
(4 answers)
Closed 1 year ago.
this may be blurry to grasp but i'm new to java whole thing and i want to know how can i use cmd to type something in user input
E:\My apps\Java apps\test\src\main\java>java ls.java && echo E:/
enter File name or path :
in this input i want to enter the path via cmd the "&& echo E:/" doesn't work
You can use "Command Line Arguments" in order to give the input when running the program!
Assuming your file name is ls.java
compile it using: javac ls.java
when running it using java command type the arguments in front of it like:
java ls E:/path
Now you can catch the arguments in the program
public class ls {
public static void main(String[] args)
{
String path = args[0];
}
}
you can add more arguments by spaces and catch them in String array
java ls E:/path 100 200
System.out.println(args[1]); // will print 1
System.out.println(args[2]; //will print 200
NOTE: As implied all the command line arguments are stored in the form of String, if you want to convert them to another format, you'd need to parse them using methods.

How do I Remotely shutdown another computer using java

I've connected two machines in virtual box. I know that the machines are connected because I was able to detect the os of the target windows machine
Aim: Use one machine to shutdown the target windows machine using a java program which accepts a user input: ip
Problem : When the program executes it skips
runtime.exec("shutdown /m /t0 \\" +ip);
Therefore it does not shutdown the targeted computer.
Question: Why is this happening and how can I solve the issue?
import java.io.IOException;
import java.util.Scanner;
public class RemoteShutdown
{
/*Shutdown user's computer*/
public void shutdown(String ip )
{
Runtime runtime = Runtime.getRuntime();
try
{
runtime.exec("shutdown /s /m \\" +ip);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
Scanner scanner = new Scanner(System.in);
RemoteShutdown shutDown = new RemoteShutdown();
System.out.print("Enter computer IP: ");
String IP = scanner.next().trim();
shutDown.shutdown(IP);
}
}
relative paths are usually a bad idea in runtime.exec. You have little control of the path; a better option would be to fetch the windows home dir via System.getenv and craft your own route to C:\Windows\System32, or wherever 'shutdown.exe' lives.
Usually this needs admin access, so what you want may be impossible, or may requiring launching java with admin rights.
Generally, don't use exec, but use ProcessBuilder. Trying to navigate how args are split is rather confusing with just the basic exec.
In java, \ in a string is an escape single. "\\" is a string containing only one backslash, but you want to send 2 backslashes to windows here, so, in java, you'd write "\\\\" + ip.
exec returns a Process object, and you tell it to combine output and error, and then you can fetch the output and error streams. This helps a lot: In this case, no doubt shutdown.exe is telling you that the specification of the other computer is erroneous (due to, effectively, a missing backslash), but you never read this data. A web search for 'ProcessBuilder java example read output' will probably get you multiple in-depth posts.

how to pass parameter to shell script to use as part of variable filename [duplicate]

This question already has answers here:
How do I parse command line arguments in Bash?
(40 answers)
Closed 4 years ago.
I am trying to programmatically call from my java program a shell script that in turn executes a command depending of the parameter sent.
the command to be executed inside the connectvpn.sh shell script is:
echo myrootpassword | sudo -S /usr/local/Cellar/openvpn/2.3.8/sbin/openvpn --config /usr/local/etc/openvpn/1.opvn
or
echo myrootpassword | sudo -S /usr/local/Cellar/openvpn/2.3.8/sbin/openvpn --config /usr/local/etc/openvpn/2.opvn
and so on from a long list, where the filename number I want to be variable depending on the value of the parameter received
So I want my java program to be able to use always the same shell script but use different .ovpn file depending on the parameter sent.
I believe that on my java program I have to call it something like this:
server_number = 1;
ProcessBuilder pb = new ProcessBuilder("./connectvpn.sh", server_number);
Process proc = pb.start();
What would go in the shell script so that the filename called is variable and for the example shown it uses 1 but other times it uses whatever number is sent as parameter?
Thank you very much!
In the shell script, use $1 to denote the first parameter passed to it.
Fix your java as below,
ProcessBuilder pb = new ProcessBuilder("./connectvpn.sh", String.valueOf(server_number));

Why does System.console() return null for a command line app? [duplicate]

This question already has answers here:
System.console() returns null
(13 answers)
Closed 8 years ago.
I am working on a legacy app which depends on user command line input:
String key = System.console().readLine("Please enter the license key: ");
However, I am getting a NullPointerException because System.console() gives me a null.
Why does System.console() return null for a command line app? It happens when running it out of the terminal as well as IDE.
If you start java from a terminal window, then it really should work, even though I haven't tried on OSX.
If you run a simple test using java directly from the terminal, does it work?
echo 'public class Test { public static void main(String[] args) {System.console().printf("hello world%n");}}' >Test.java && javac Test.java && java Test
Expected output:
hello world
If it doesn't work, then sorry, no console support on your platform.
However, if it works, and your program doesn't then there is a problem with how your program is started.
Check how the java binary started? Is it started from a shell script? Check that stdin/stdout have not been redirected or piped into something, and possibly also that it's not started in the background.
ex: This will probably make System.console() return null.
java Test | tee >app.log
and this:
java Test >/tmp/test.log
This seems to work on my machine (linux)
java Test &
Neither does it seem as if System.setOut, System.setErr or System.setIn affects the console, even after a couple of gc's and finalizers.
However:
Closing (the original) System.out or System.in will disable the console too.
echo 'public class Test { public static void main(String[] args) {System.out.close();System.console().printf("hello world%n");}}' >Test.java && javac Test.java && java Test
Expected output:
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:1)
So; scan your code for places where it closes streams, or passes System.out somewhere it might get closed.
To read from Standard input (command line input) you must use some kind of stream reader to read the System.in stream.
An InputStreamReader initialised by
InputStreamReader(System.in)
lets you read character by character.
However, I suggest wrapping this with a BufferedReader:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String inputLine = reader.readLine();
Must import
java.io.*;

Setting nice value of Java program running on linux

I want my Java program to lower it's priority some so it doesn't overwhelm the system. My initial thought was to use Thread.currentThread().setPriority(5) but that appears to be merely its priority within the JVM.
Then I thought maybe I'd cludge it and invoke a system command, but Thread.getId() is also merely the JVM's id, so I don't even know what process id to pass to renice.
Is there any way for a Java program to do something like this?
Since we must do it in a platform dependent way, I run a shell process from java and it renices its parent. The parrent happens to be our java process.
import java.io.*;
public class Pid
{
public static void main(String sArgs[])
throws java.io.IOException, InterruptedException
{
Process p = Runtime.getRuntime().exec(
new String[] {
"sh",
"-c",
"renice 8 `ps h -o ppid $$`"
// or: "renice 8 `cat /proc/$$/stat|awk '{print $4}'`"
}
);
// we're done here, the remaining code is for debugging purposes only
p.waitFor();
BufferedReader bre = new BufferedReader(new InputStreamReader(
p.getErrorStream()));
System.out.println(bre.readLine());
BufferedReader bro = new BufferedReader(new InputStreamReader(
p.getInputStream()));
System.out.println(bro.readLine());
Thread.sleep(10000);
}
}
BTW: are you Brad Mace from jEdit? Nice to meet you.
If your program is the only running java program, then you can run
renice +5 `pgrep java`
In addition to renice - you may also use ionice comand. For example :
ionice -c 3 -n 7 -p PID
Also look at https://github.com/jnr/jnr-posix/.
This POSIX library should allow you to get at some of the Linux Posix Nice functions like...
https://github.com/jnr/jnr-posix/blob/master/src/main/java/jnr/posix/LibC.java for the OS level setPriority(), i.e. setpriority(2)
jnr-posix is also in Maven.
Use:
nice --adjustment=5 java whatever
to run your java program and assign the priority in just one step.
My suggestion is to invoke your java application from a bash script or start/stop service script then find the process id after startup and renice it.

Categories