Unable to execute my command after SSH in remote server - java

I have written a code that does SSH in servers and runs a Java file with arguments.
The problem I am facing is that the code successfully does SSH in but it does not run the command after that. Strangely If I run the command from the server alone it works. Any suggestions on this please?
Following is the code:
public void getSSH(String code, String newCode, JspWriter out){
try{
File f = new File("/usr/site/html/Output.txt");
BufferedWriter output = new BufferedWriter(new FileWriter(f));
String Servers[] = {"root#web233.xyz.com","root#web234.xyz.com","root#web235.xyz.com","root#web153.xyz.com"};
for(int i =0;i<Servers.length && i<1 ;i++){
Process p = Runtime.getRuntime().exec("/usr/site/swapimages.sh "+Servers[i]+" '/root/testRemote.sh "+ code+" "+ newCode+"'");
out.println("/usr/site/swapimages.sh "+Servers[i]+" '/root/testRemote.sh "+ code+" "+ newCode+"'"+"<br>");
Utils.waitFor(10000);
}
}
}
I have also been recommended JSch but haven't looked into it yet.

The reason it isn't working is that the quotes in this version don't have the same effect as they do on the command line. When you call SSH from bash, you put the remote command in quotes so that it is all interpreted as a single argument. Bash does the separation of the arguments for you. With exec, Java is splitting up the arguments for you. The documentation for exec describes how it separates. It uses a StringTokenizer, which is fairly dumb and seperates the line based on spaces (ignoring the quotes). This means that the array of arguments passed into the command is something like:
{ "/usr/site/swapimages.sh", "root#something", "'/root/testRemote.sh",
code, newCodeContents + "'" }
It could be even more strings if code or newCode have spaces in them. Notice that your command is multiple elements in the array and will therefore be treated as multiple arguments by ssh. In addition, ssh will actually try to execute a command that is in a directory that is named '. What you want to pass in, though, is:
{ "/usr/site/swapimages.sh", "root#something",
"/root/testRemote.sh " + codeContents + " " + newCodeContents }
Notice that there are no quotes and the whole command is the third element in the array.
So, you just need to manually create the string array and use the other form of exec that takes a string array and that should fix the problem.

Related

How do I increase command line argument size or limit in windows command prompt

Hi I have created a JAVA program which uses ProcessBuilder to start command prompt, java passes command with some arguments to the console and then command prompt is responsible to handle the command, everything is working fine until the command line argument is too long. Actually I am using phantomjs as a command and passing multiple urls as a arguments to the command prompt.
Eg: Java generated string-
phantomjs download.js --url=http://google.com, http://yahoo.com, http://website.com..................http://demo.com
When I was passing 100's of urls then it works fine but when increases to 1000's of urls then its not working. I know, it happens because of argument buffer size. When I was trying to pass 1000's urls then it exceeds the maximum byte limit of the command line for windows. So there is any other way to pass this value into file or can we increase the limit of command line arguments.
Please give me some solution for this.
Why not just passing a filename as argument ?
The target file contains the list of urls (JSON.stringify or simply one per line)
For example
var system = require('system');
var fs = require('fs');
var args = system.args;
if (args.length === 1) {
console.log('download.js <filename>');
phantom.exit(1);
} else {
var filename = args[1];
var stream = fs.open(filename, 'r')
var line;
while(line=stream.readLine()) {
//do want you want here
console.log(line);
}
phantom.exit(0);
}
Run with
>phantomjs download.js mytestfile.txt

Runtime.exec() to bash javac error

I'm using Runtime.exec() to run a shell script in a Java program.
The script basically compiles a java program and runs it and goes something like:
./run2.sh "/Users/user/Desktop/Test.java" "Test" "/Users/user/Desktop/"
my parameters in general are the absolute path of the java file, class name and directory where the supposedly compiled class file is
my script is simply
javac "$1"
cd "$3"
java "$2"
I've tried running the resulting command in my Terminal and it works fine. however when the java program runs it, I get and error:
javac: invalid flag: "/Users/user/Desktop/Test.java"
What should I do? I've tried every possible script I can find on the internet (*edit: and I can think of, of course)
(*edit: execute statement)
// some code here...
String[] outFile = translate.translate();
try {
String params = "";
for(String sss: outFile) {
String tmp = "\"" + sss + "\"";
params += tmp + " ";
}
String command = "./run2.sh "+params;
System.out.println(command);
Process proc = Runtime.getRuntime().exec(command);
} //respective catch
the first line, String[] outFile = translate.translate() returns an array Strings of my supposedly parameters
Your mistake is including quote characters in the command string that you are passing to exec(). The exec() method does NOT know how to deal with quotes or other "shell language" stuff. You would be better off trying to execute the command something like this:
Runtime.getRuntime().exec(new String[]{command, arg1, arg2, arg3});
where the command and arguments strings DO NOT have quotes around them.

Java IOException on exec call with any command-line arguments

I've got a java application that will eventually get fairly deep into external process integration, including IPC with those processes. For now though, what I'm trying to do is simply run a powershell script from java.
what I've got:
private void runPowershellScript() {
String command =
"" + "powershell" + " ";
// Paths.get("").toAbsolutePath() + "\\" + scriptFileName + " " +
// Paths.get("").toAbsolutePath() + "\\" + INPUT_FILE_NAME + " " +
// Paths.get("").toAbsolutePath() + "\\" + OUTPUT_FILE_NAME + "";
try {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process process = builder.start();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine ()) != null) {
System.out.println ("Stdout: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
With what you see there, I get the Windows Powershell name and copyright coming out over that reader, but if I add any of the commented out lines (all of which resolve to proper paths, eg C:\Users\Geoff\Code\OPTIP\FakeProgram.ps1) I get:
java.io.IOException: Cannot run program "powershell C:\Users\Geoff\Code\OPTIP\FakeProgram.ps1 ": CreateProcess error=2, The system cannot find the file specified
I've tried a dozen different combinations of strong and weak quotes, and I've tried passing them as arguments to cmd.exe /c powershell ... but nothing I've tried runs the script. If there is a single space in the command string, I get an IO Exception.
I'm wondering if maybe it has something to do with character encoding? When I simply invoke powershell, I'm getting 'back from reader.readLine() is:
W\u0000i\u0000n\u0000 ... Which I presume is my IDE's (IntelliJ's) way of telling me its "Windows Powershell" with a null unicode character between each letter.
The Java ProcessBuilder documentation is a little vague on exactly what you can pass as arguments:
a command, a list of strings which signifies the external program file to be invoked and its arguments, if any. Which string lists represent a valid operating system command is system-dependent. For example, it is common for each conceptual argument to be an element in this list, but there are operating systems where programs are expected to tokenize command line strings themselves - on such a system a Java implementation might require commands to contain exactly two elements.
I dont know what that means. The command I'm trying to give it works from a CMD and Powershell window, and also from the windows run dialog.
gist containing the class of above method:
https://gist.github.com/Groostav/9c5913e6f4696a25430d
gist containing my powershell script:
https://gist.github.com/Groostav/347a283ac7ec6a738191
Thanks for any help.
You have to put the arguments in separate strings, not concatenating them to the powershell call as a single string.
Something like
new ProcessBuilder("Powershell", scriptFileName, INPUT_FILE_NAME);

How to run bat file from java with arguments (i.e file name with full path) having folder name with space

Am trying to execute the a bat file with some arguments through a JAVA programmes . the arguments are file name with full path, And this path had some folder name with space, which are creating issue and giving me the following error
Error: 'D:\Documents' is not recognized as an internal or external
command
the code is as below
String command = "D:\Documents and Settings\ A.bat" + " " D:\Documents and Settings\B.xml
1. process = Runtime.getRuntime().exec(new String[] {"cmd.exe","/c",command});
2. process.waitFor();
3. exitValue = process.exitValue();
You need to escape the \ in your string (i.e. doubling them: D:\\Documents), but that is not the problem. You can try to escape the spaces Documents\\ and\\ Settings or you use the exec method that does this for you. Just dont build the command line by yourself. Better use ProcessBuilder for starting processes.
String command = "\"D:\Documents and Settings\\" A.bat" + " \"D:\Documents and Settings\B.xml\""
Escape double quotes, so you can include double quotes in the literal, to give:
cmd.exe /x "D:\Documents and Settings\" A.bat "D:\Documents and Settings\B.xml"
I was trying to do the same thing. I googled whole day but didn't make it work. At Last I handled it in this way, I am sharing it if it comes to any use of anybody :
String command = "A.bat D:\\Documents and Settings\\B.xml";
File commandDir = new File ( "D:\\Documents and Settings ");
String[] cmdArray = { "cmd.exe", "/c", command };
1. Process process = Runtime.getRuntime().exec( cmdArray, null, cmdArray );
2. process.waitFor();
3. exitValue = process.exitValue();
I've spent a while searching on SO and the wider Internet and was about to post this as a new question when I came across this, which does seem identical to my issue...
I am trying to call a Windows batch file from Java. The batch file takes several arguments but just the first, which is a path to a data file, is of relevance to this problem. The cut-down command line that I have been experimenting with is essentially:
cmd /c c:\path\to\my\batchfile.bat c:\path\to\my\datafile.mdl
I'm using Apache Commons Exec which ultimately delegates to Runtime.getRuntime().exec(String[] cmdarray, String[] envp, File dir), the 'correct' version as opposed to the overloaded versions taking a single String command. Quoting of the arguments when they contain spaces is therefore taken care of.
Now, both the path to the batch file and/or the path to the data file can have spaces in them. If either the path to the batch file or the path to the data file have spaces in, then the batch file is executed. But if both have spaces in them then the path to the batch file is truncated at the first space.
This has to be a (Java or Windows?) bug, right? I've debugged right down to the native call to create() in java.lang.ProcessImpl and all seems ok. I'm on JDK1.6.

Java simple networking program works in Eclipse, not in terminal

I wrote a simple networking program in Java that reads text from a text file on the server side and sends it to the client. The client program writes the text to a text file on the client computer.
I'm testing the program on one computer (localhost), and it works in Eclipse but when I try to run it from the terminal, I get a runtime error on the server side. It seems to be a problem with the Scanner that reads the text from the server's text file, but I'm note sure.
Here is the error:
Exception in thread "main" java.lang.NullPointerException
at java.util.regex.Matcher.toMatchResult(libgcj.so.10)
at java.util.Scanner.myCoreNext(libgcj.so.10)
at java.util.Scanner.myPrepareForNext(libgcj.so.10)
at java.util.Scanner.myNextLine(libgcj.so.10)
at java.util.Scanner.hasNextLine(libgcj.so.10)
at pkg.TextTransmitServer.sendText(TextTransmitServer.java:50)
at pkg.TextTransmitServer.main(TextTransmitServer.java:26)
Double check that you are using the same input file in both cases. Are you using fully qualified paths when you open the file? If the files are different, it would explain why a regular expression works with one and not the other.
Please add two things to the question. 1) code snippet of how the file is opened, and 2) code snippet of the regex usage. Interesting observation: why is java.util.Scanner.hasNextLine(libgcj.so.10) using a regex? Did you have to pass one in?
Not sure why you are using 'hasNextLine()'. Try with hasNext() after setting the delimiter to be the line separator. See this page for more examples.
private static void readFile(String fileName) {
try {
Scanner scanner = new Scanner(new File(fileName));
scanner.useDelimiter
(System.getProperty("line.separator"));
while (scanner.hasNext()) {
System.out.println(scanner.next());
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Either the delimiter being used by hasNextLine() is null or the inputline being scanned is null. Print out the offending input line from the file when the the NPE is thrown. Without your code this is just a shot in the dark but something like this:
[in or near pkg.TextTransmitServer.sendText(TextTransmitServer.java:50) ]
try {
String currentLine = null;
String previousLine = null;
while (scanner.hasNext()) {
previousLine = currentLine;
currentLine= parseLine(scanner.next());
}
}
catch (NullPointerException npe) {
System.out.println("previous line: " + previousLine);
System.out.println("current line: " + currentLine);
npe.printStackTrace();
}
As a pointer in getting to the root of the issue you can debug your java application from command line by adding the following parameters to your java command-
-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
And then connect eclipse to the remote debugger using 8000 port. This will help you easily get to the bottom of the issue.
Make sure that your scanner can handle different charsets/consoles correctly. It might be that one of the two setups uses e.g. UTF-8 and may thus see multi-bytes for a single character (or rather the other way round if your protocol encodes the length of the string).
Ok, first, as #Kelly states check if you are reading same file in both cases.
Now, I get a feeling that you moved your whole project from Sun JVM ( Eclipese on your desktop ) to another JVM ( from your exceptions it is clear that you are running on Linux , default JVM ) . This might be due to a bug in that JVM
Consider using Sun's JVM instead of GCJ ( default JVM on linux)

Categories