I am trying to run a program which process a file from window using jcraft library in Unix. what i found after establishing the channel it always try to run the program in home directory but i need to run in a separate directory.please have a look what i tried so far and let me know what i am missing.
String strRemoteDir = "/home/process/input"
channel = session.openChannel("sftp");
channel.connect();
System.out.println("sftp channel opened and connected.");
channelSftp = (ChannelSftp) channel;
// Printing Home Directory in Unix Server
System.out.println(channelSftp.getHome());
channelSftp.cd(strRemoteDir);
System.out.println(channelSftp.pwd());
// for uploading a file where i need to run the program
File f = new File(fileName);
channelSftp.put(new FileInputStream(f), f.getName());
System.out.println("File transfered successfully to host.");
fileTransfer = true;
channel=session.openChannel("exec");
InputStream in=channel.getInputStream();
// it is printing the desired directory where i want to go
System.out.println(channelSftp.pwd());
((ChannelExec)channel).setCommand("sh process.ksh "a.txt");
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
channel.connect();
output : process.ksh not found
But through putty i was able to run the program. just to let you know process.ksh is not in the input directory, but has the capability to run from anywhere with arguments.
((ChannelExec)channel).setcommand("ls")
prints out all the files from home directory. i believe i am establishing a channel to home directory, i just don't know how to run bash program using jcraft in a desired location.Please let me know what i am missing or is it possible to make it happen.
Thanks in advance.
Nur
"sftp" channel are not made to execute shell command but sftp command only.
Channel channel = session.openChannel("shell");
cmdSend = channel.getOutputStream();
InputStream cmdRcv = channel.getInputStream();
// Start a Thread reading and displaying cmdRcv
channel.connect(3000);
Thread.sleep(1000);
cmdSend.write("cd /to/the/right/dir\n".getBytes());
cmdSend.flush();
cmdSend.write("sh process.ksh \"a.txt\"\n".getBytes());
cmdSend.flush();
Others have provided examples of how to set the working directory. However, a more defensive style of programming is to assume nothing and specify everything explicitly. So for specifying the command to execute, something like:
/bin/sh /path/to/bin/process.ksh /path/to/data/ "a.txt"
Notice that I have added a new first argument to your command, the directory you want to run it from.
Now, change your script so that it changes to this directory (given as parameter $1) before continuing.
This can be done by adding cd at the beginning, something like:
cd $1
shift
The shift command shifts all other arguments, so that $2 becomes $1 and so on, so that the rest of the script will find the arguments where it expects.
Related
I am very new to JSch. I am trying to run few commands on a server which I am getting as input from some other system.
What I am doing is taking those commands and passing them as a parameter to a java method.
For Eg:
public String readFileFromPath(String server, String path,
String fileName);
Here first we have to cd to 'path', then we need to read some particular content from the file present on the path.
To implement this I did following :
Session session = sshOperations.getSessionWithTimeout(USER,server,SSHPORT,1000);
Channel shellChannel = sshOperations.getShellChannel(session);
InputStream in = new PipedInputStream();
PipedOutputStream consoleInput = new PipedOutputStream((PipedInputStream) in);
OutputStream out = new PipedOutputStream();
BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(new PipedInputStream((PipedOutputStream) out)));
shellChannel.setInputStream(in);
shellChannel.setOutputStream(out);
shellChannel.connect(1000);
consoleInput.write(("cd "+path).getBytes());
// first While
while ((line = consoleOutput.readLine()) != null)
{
System.out.println("check "+ line);
}
// execute second command
consoleInput.write("cat some.properties".getBytes());
// second While
while ((line = consoleOutput.readLine()) != null)
{
System.out.println("check "+ line);
}
Now what I know is whenever I connect to that server I get a welcome text :
"You are using <serverName> server.
Please contact admin for any issues"
So, after the first while loop my cd command ran and it prints the message mentioned above. But, after this it waits for more output from the output stream (it is stuck at this point )and the output stream can't product anything until I run another command.
Somehow I want to exit from the first while loop without writing the logic for consuming the 2 lines(fixed lines). As for the next command I will not know how many lines will come as output in stream.
Please suggest the logic to the get the desired output i.e. I ran a command and some logic consumes it and then I get get to run another command and so on until all the commands which came as parameter are executed.
Is there any other way to achive the same?
Thanks
Do not use "shell" channel. The "shell" channel is intended to implement an interactive session (hence the welcome message), not to automate command execution.
To automate command execution, use "exec" channel. See Multiple commands through JSch shell.
Though you actually do not need multiple commands. There's no need for cd. Just use a full path in the cat command
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("cat " + path + "/some.properties");
channel.connect();
Though actually, if you want to read contents of files, use SFTP, instead of running console commands like cat. SFTP is a standardized API to access files over SFTP.
See SFTP file transfer using Java JSch.
I want to concatenate two dos commands in a java program. First I want to change directory then list the files and folders in that. So I wrote that like
try
{
Process process = UI.this.rt.exec("cmd.exe /c cd C:\\Users & start dir");
process.waitFor();
InputStream in = process.getInputStream();
while (in.read() != -1) {}
}
catch (Exception e)
{
System.out.println(e);
}
But this is not working. When I execute this in desktop it is not change the directory and display the files and folders which is in the desktop. Could you please help me to fix this problem? I'm using windows 7 machine.
Thanks
Isuru Liyanage
Write the commands to a batch file on the disk and execute the batch.
If you don't want to have such a batch on the disk, create it on demand and delete it after usage.
Or just use the java build-in features to list files.
EDIT
But your code works. I tried it.
It opens a dos-box an lists the directory after changing the directory.
You can use ProcessBuilder to set the working directory of the Process you exec later.
Or, do as suggested else-thread and use the Java API for listing files in a directory, which is saner.
While creating a process you can pass a string array of commands as below:
String[] command = new String[3];
command[0] = "cmd";
command[1] = "/c";
command[2] = " cd c:\\Users && dir";
Process p = Runtime.getRuntime().exec(command);
Drop the start, it runs files in a new window. Plus as there in no cmd in the NEW command DIR won't be recognised as a command. If you must use start for some reason add cmd /c to the dir part as well.
also dir c:\users is all you actually need to do. No need or reason to change directory.
I am trying to call a python script from a java/tomcat6 webapp. I am currently using the following code:
Process p = Runtime.getRuntime().exec("python <file.py>");
InputStream in = p.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader b = new BufferedReader(isr);
logger.info("PYTHON OUTPUT");
String line = null;
while ( (line = b.readLine()) != null){
logger.info(line);
}
p.waitFor();
logger.info("COMPLETE PYTHON OUTPUT");
logger.info("EXIT VALUE: "+p.exitValue());
I can't really see any output in the catalinia.out file from the python script and using an adapter library like jython is not possible as the script relies on several machine learning libraries that need python's Numpy module to work.
Help?
The explanation is probably one (or more) of following:
The command is failing and writing error messages to its "stderr" fd ... which you are not looking at.
The command is failing to launch because the command name is incorrect; e.g. it can't be found on $PATH.
The command is trying to read from its stdin fd ... but you haven't provided any input (yet).
It could be a problem with command-line splitting; e.g if you are using pathnames with embedded spaces, or other things that would normally be handled by the shell.
Also, since this is python, this could be a problem with python-specific environment variables, the current directory and/or the effective user that is executing the command.
How to proceed:
Determine if the python command is actually starting. For instance. "hack" the "" to write something to a temporary file on startup.
Change to using ProcessBuilder to create the Process object. This will give you more control over the streams and how they are handled.
Find out what is going to the child processes "stderr". (ProcessBuilder allows you to redirect it to "stdout" ...)
I am trying to change user password in linux from java program by sending password in outputstream but it is not done.
My java program is like
Process process = Runtime.getRuntime().exec("sudo passwd sampleuser");
OutputStream outputStream = process.getOutputStream();
InputStream inputStream = process.getInputStream();
PrintWriter printWriter=new PrintWriter(outputStream);
printWriter.write("123456");
printWriter.write("\n");
printWriter.flush();
My program fails here and it ask for password but I does not want this case.
Is there any possibility for providing password from java program ? can you suggest me,how I will do it successfully or is there any shell api's available for it.
Same thing is done successful when I try using shell script and calling it from my java program as
Process process = Runtime.getRuntime().exec("bash first.sh");
My shell script is
i="123456"
echo -e $i"\n"$i|sudo -S passwd sampleuser
It changes user password successfully.
It will ask for password. Look at your shell script. You execute a command that asks for super user privileges(sudo). Your program will prompt for a password unless you run it as a super user.
To break down your shell script:
i="123456"
echo -e $i"\n"$i|sudo -S passwd sampleuser
sudo -S means :
The -S (stdin) option causes sudo to read the password from the standard input instead of the terminal device. The password must be followed by a newline character.
And that is what your script is doing, it is setting password(passwd) for your sampleuser as i. And since you are using -S it is reading from the standard input,to which you have already given your variable i. And you are doing all this as a super user! keep that in mind.
Now look back at your java program and try for the changes accordingly. Do you have super user privileges when you run your program? No,you don't.
I'm not sure why your approach fails. I suppose passwd uses a different stream.
But use ExpectJ for this. It is made just for such cases.
If someone is looking for an answer, I just find a way with this lines :
try {
Process p = Runtime.getRuntime().exec(new String[] {"sudo", "/bin/sh", "-c", "echo \"user:newpassword\" | sudo chpasswd"} );
p.waitFor();
} catch (IOException | InterruptedException e1) {
e1.printStackTrace();
}
I am executing command from java program like
Process myProcess = Runtime.getRuntime().exec("sudo cat /etc/sudoers"); //It asks for password so I send password through outputstream from my program.
InputStream inputStream = myProcess.getInputStream();
OutputStream outputStream = myProcess.getOutputStream();
outputStream.write("mypassword".getBytes()); // write password in stream
outputStream.flush();
outputStream.close();
But problem is that, it again ask to me for password as I already send the password through outputstream from my program.
For solving this I tried so many times but not actually done.
By using shell script,I am able to provide password to terminal and my program works fine
but it is not the most flexible way.
Can you suggest me any way for providing password through my java program ? (instead of shell programming)
You can do it using the -S option of sudo :
String[] cmd = {"/bash/bin","-c","echo yourpassword| sudo -S your command"};
Runtime.getRuntime.exec(cmd);
But I'm not sure it's recommendable.
I'm not the author, I found this there : http://www.coderanch.com/t/517209/java/java/provide-password-prompt-through-Java