scp using Jsch to copy file asking for password - java

I am trying to copy files from one remote server to another remote. I tried to use scp. It's copying the files through putty but not through the code. I am currently using echo to copy the files. With echo I am writing a string finalStr to abc.bcc its working fine. But when using below command in Jsch its not working.
scp /home/abc.bcc user#host:/folder1/folder2/abc.bcc
I tried adding ssh public private keys but no luck. I tried with channel.setPty(true) to avoid password prompt and setting the password through bufferedWriter. But still unable to copy the files. Please suggest what needs to be changed.
JSch jsch = new JSch();
Session session;
try {
session = jsch.getSession("user", "host", 22);
session.setPassword("password");
session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
logger.info("Connection status: " + session.isConnected());
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(
"echo \"" + finalStr + "\" >> /folder1/folder2/abc.bcc");
((ChannelExec) channel).setPty(false);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
channel.connect();
logger.info("Channel status : " + channel.isConnected());
out.write("\n".getBytes());
out.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = br.readLine()) != null) {
logger.info(++index + " : " + line);
}
channel.disconnect();
session.disconnect();
}catch(....
Debug output:
debug1: Trying private key: /home/build_path/.ssh/id1
debug3: no such identity: /home/build_path/.ssh/id1: No such file or directory
debug1: Trying private key: /home/build_path/.ssh/id2
debug3: no such identity: /home/build_path/.ssh/id2: No such file or directory
debug1: Trying private key: /home/build_path/.ssh/id3
debug3: no such identity: /home/build_path/.ssh/id_3: No such file or directory

The log looks like user home is not set correctly! So it doesnt find the key files!
General approach:
get the ssh to work without the code.
to copy from one remote to another requires the hostnames and connections to be resolved on both remotes for each other. so login to one remote and try the ssh connection from there directly to the other remote. This is not guaranteed to work.
I am pretty sure once you have this resolved you get everything else working.
When proxies are involved this can get quite complicated as the proxy settings have to work correctly between all 3 machines.
I am facing those issues repeatedly and it can be very messy.

Related

Unable to access the cmd prompt in remote machine using openchannel in java

I'm trying to access the cmd prompt in administrator mode and run a batch file in the remote machine,but right now I'm not able to access the cmd prompt through openchannel. Did anybody tried to access it from remote machine in java?
Here is the code
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
session = jsch.getSession(user, ip, 22);
session.setPassword(password);
session.setTimeout(timeOut);
session.setConfig(config);
session.connect();
System.out.println("session connected");
//open command prompt to run the command = "C:\\executeBatchFile.bat" file
Channel channel = (ChannelExec) session.openChannel("exec");
((ChannelExec)channel).setCommand("cmd.exe /c \"echo %cd%\"\\executeBatchFile.bat");
channel.connect();
InputStream outputstream_from_the_channel = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
String jarOutput;
while ((jarOutput = reader.readLine()) != null)
{
System.out.println("Inside while loop");
System.out.println(jarOutput + "\n");
}
reader.close();
session.disconnect();
Expected behavior :set command should run as an administrator(though I have logged in as admin),come back to the c:drive (cd) and execute the batch file ie; C:executeBatchFile.bat
Actual behaviour : command gives the user path(not as admin) when I print the jarOutput. ie; C:\Users\Admin\executeBatchFile.bat
could you suggest any solution on the same?
This has been resolved using PsExec command instead of JSCH
String pscommand=E:\\Tool\\psexec -u user -p pwd \\\\ip -s -d cmd.exe /c C:\\executescript.bat
process = Runtime.getRuntime().exec(pscommand);
InputStream es = process.getErrorStream();
BufferedReader errReader = new BufferedReader(new InputStreamReader(es));
String line;
// Read STDOUT into a buffer.
while ((line = errReader.readLine()) != null)
{
system.out.println(line);
}
Could any one tell me how to open the cmd prompt in administrator mode(I logged in using admin credentials only but still it does not open in admin mode).Here I need to run the script in administrator.

Transfer file and change user using Java to unix box

I want to transfer file from windows to unix(linux) box using Java, then change to super user. I tried using the JSCH library, that is SFTP with java.
I am stuck at the step to change to super user.
The steps i followed are similar to how to transfer a file through SFTP in java?
I know similar questions have been asked, but i am not able to change user using this approach.
Request to please do not mark this as duplicate.
Can anyone help me with the steps, or any other approach? An example would be helpful for the same. Thanks in advance.
Edit-1 - sample snippet from the link how to transfer a file through SFTP in java?, which is used as a reference posted
public void send (String fileName) {
String SFTPHOST = "host:IP";
int SFTPPORT = 22;
String SFTPUSER = "username";
String SFTPPASS = "password";
String SFTPWORKINGDIR = "file/to/transfer";
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
System.out.println("preparing the host information for sftp.");
try {
JSch jsch = new JSch();
session = jsch.getSession(SFTPUSER, SFTPHOST, SFTPPORT);
session.setPassword(SFTPPASS);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
System.out.println("Host connected.");
channel = session.openChannel("sftp");
channel.connect();
System.out.println("sftp channel opened and connected.");
channelSftp = (ChannelSftp) channel;
channelSftp.cd(SFTPWORKINGDIR);
File f = new File(fileName);
channelSftp.put(new FileInputStream(f), f.getName());
log.info("File transfered successfully to host.");
} catch (Exception ex) {
System.out.println("Exception found while tranfer the response.");
}
finally{
channelSftp.exit();
System.out.println("sftp Channel exited.");
channel.disconnect();
System.out.println("Channel disconnected.");
session.disconnect();
System.out.println("Host Session disconnected.");
}
}
With this, i am able to connect to the remote system, but cannot change the user.
Edit-2 : On doing some more research, i could find that using SFTP with JSCH api can help me transfer the file, but not change user. If i change the Channel to 'exec', i can change the user, but both do not work in same session. So both do not work simultaneously.
Is there any another way (SSH, SCP transfer perhaps?)
So the question remains unsolved - Want to transfer file and change user through Java.

Invoke WLST commands with JSch

I'm trying to run a restart server command on WLST through a remote Java web app.
This is what I'm trying to execute:
StringBuilder sb = new StringBuilder();
sb.append("/u01/app/oracle/jdk1.8.0_65/bin/./java -cp /u01/app/oracle/product/Oracle_Home/wlserver/server/lib/weblogic.jar weblogic.WLST");
sb.append(";connect(\'weblogic\',\'" + consolePass + "\',\'" + fullAddress + "\')");
sb.append(";domainRuntime()");
sb.append(";cd(\'/ServerLifeCycleRuntimes/" + serverName + "\')");
sb.append(";cmo.shutdown())");
sb.append(";start(" + serverName + ",'Server')");
String command = sb.toString();
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setUserInfo(new OracleUserInfo(pass));
session.connect();
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
if (in.available() > 0)
continue;
System.out.println("exit-status: " + channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
}
}
channel.disconnect();
session.disconnect();
I'm using ';' to separate the commands, since I thought it was required to run multiple commands.
Unfortunately, it gives a syntax error on line 2.
bash: -c: line 0: syntax error near unexpected token 'weblogic','password','t3://host:7001''
bash: -c: line 0:/u01/app/oracle/jdk1.8.0_65/bin/./java -cp /u01/app/oracle/product/Oracle_Home/wlserver/server/lib/weblogic.jar weblogic.WLST;connect('weblogic','password','t3://host:7001')'
I tried to add \n after the first line, and the result was that the first line was executed (so it entered WLST), but none of the remaining commands were.
StringBuilder sb = new StringBuilder();
sb.append("/u01/app/oracle/jdk1.8.0_65/bin/./java -cp /u01/app/oracle/product/Oracle_Home/wlserver/server/lib/weblogic.jar weblogic.WLST\n");
sb.append(";connect(\'weblogic\',\'" + consolePass + "\',\'" + fullAddress + "\')\n");
sb.append(";domainRuntime()\n");
sb.append(";cd(\'/ServerLifeCycleRuntimes/" + serverName + "\')\n");
sb.append(";cmo.shutdown())\n");
String command = sb.toString();
Result:
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
wls:/offline>
I tested the command manually and it worked. The problem seems to be with JSch with WLST interface, since it opens another shell interface.
Any ideas how I could run WLST commands with JSch?
PS1: I know my JSch code works because I have a feature on the same app to deploy. Basically, it runs a jscp to upload the war, and then ssh to execute the weblogic.Deployer -deploy command.
PS2: I do have a .py script to do that, but as of now, it must be on the server to be executed. I'm thinking about doing an jscp to a temp folder, run the script and then delete. But I'm curious to find out how to run multiple commands on WLST with JSch.
Thanks in advance.
UPDATE
Code working (Thanks Martin)
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
((ChannelExec) channel).setErrStream(System.err);
channel.connect();
for (String wlstCommand : wlstCommands) {
out.write((wlstCommand).getBytes());
}
out.flush();
The ; can indeed by used in *nix based system to execute multiple commands in one shell command-line.
But what you are executing are not shell commands. Those are WLST commands, right? So you have to feed them to WLST.
Like this:
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand("java -cp /.../weblogic.jar weblogic.WLST");
OutputStream out = channel.getOutputStream();
channel.connect();
out.write(("connect('weblogic'...)\n").getBytes());
out.write(("domainRuntime()\n").getBytes());
...
It's basically the same as generic Providing input/subcommands to command executed over SSH with JSch.

Providing input/subcommands to command executed over SSH with JSch

I'm trying to manage router via Java application using Jcraft Jsch library.
I'm trying to send Router Config via TFTP server. The problem is in my Java code because this works with PuTTY.
This my Java code:
int port=22;
String name ="R1";
String ip ="192.168.18.100";
String password ="root";
JSch jsch = new JSch();
Session session = jsch.getSession(name, ip, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
System.out.println("Connection established.");
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("enable");
channelExec.setCommand("copy run tftp : ");
//Setting the ip of TFTP server
channelExec.setCommand("192.168.50.1 : ");
// Setting the name of file
channelExec.setCommand("Config.txt ");
channelExec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
session.disconnect();
I get
Line has an invalid autocommand '192.168.50.1'
The problem is how can I run those successive commands.
Calling ChannelExec.setCommand multiple times has no effect.
And even if it had, I'd guess that the 192.168.50.1 : and Config.txt are not commands, but inputs to the copy run tftp : command, aren't they?
If that's the case, you need to write them to the command input.
Something like this:
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channelExec.setCommand("copy run tftp : ");
OutputStream out = channelExec.getOutputStream();
channelExec.connect();
out.write(("192.168.50.1 : \n").getBytes());
out.write(("Config.txt \n").getBytes());
out.flush();
In general, it's always better to check if the command has better "API" than feeding the commands to input. Commands usually have command-line arguments/switches that serve the desired purpose better.
A related question: Provide inputs to individual prompts separately with JSch.

JSCH: No such file error

I have windows machine with running ssh server. I know the path on that machine. Let it be D:/Folder1/Folder2. I'm creating sftp channel using JSCH. But when i try to cd to D:/Folder1/Folder2, "No such file: 2" error is throwed.
can anyone please help? May be i need to convert path?
the problem is the path. It is not finding the file to rename, if you are using the JSCH library you can use
channelSftp.pwd ()
to know the current location.
Example:
Sftp sftp = new Sftp();
sftp.conectar();
ChannelSftp channelSftp = sftp.getChannelSftp();
channelSftp.rename(channelSftp.pwd()+"//"+file,`channelSftp.pwd()`+"//"+"new_dir//"+file);
//or
String url = channelSftp.pwd();
String url_m = channelSftp.pwd()+"/"+directory;
channelSftp.rename(url+file,url_m+file)
I've solved the problem by using ChannelExec by opening exec channel. This worked for me. Hope will work for others too.
...
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch ssh = new JSch();
session = ssh.getSession(sshSolrUsername, sshSolrHost, 22);
session.setConfig(config);
session.setPassword(sshSolrPassword);
session.connect();
channel = session.openChannel("exec");
((ChannelExec)channel ).setCommand("cd " + sourcePath);
exec.setInputStream(null);
((ChannelExec)channel ).setErrStream(System.err);
InputStream in = channel .getInputStream();
channel .connect();
int status = checkStatus(channel , in);
channel.disconnect();
...
I suggest you to read your file in inpuStream, then use the function:
put(InputStream src, String dst)
doc: https://epaul.github.io/jsch-documentation/simple.javadoc/com/jcraft/jsch/ChannelSftp.html
Example:
String fileName = "D:/Folder1/Folder2";
File initialFile = new File(fileName);
InputStream targetStream = new FileInputStream(initialFile);
channelSftp.put(targetStream, "./in/");

Categories