File uploaded with JSch is not visible in the target directory - java

I have written below logic using JSch API to upload a PDF file to an SFTP server. The code executes fine, but I can't see the file in the expected folder.
String localFile = "/usr/local/test.pdf";
String remotePath = "/tmp/test.pdf";
JSch jsch = new JSch();
jsch.setKnownHosts("/home/wasadm/.ssh/known_hosts");
jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT);
jschSession.setPassword(PASSWORD);
jschSession.connect(SESSION_TIMEOUT);
Channel sftp = jschSession.openChannel("sftp");
sftp.connect(CHANNEL_TIMEOUT);
ChannelSftp channelSftp = (ChannelSftp) sftp;
channelSftp.put(localFile, remotePath);

The second argument of ChannelSftp.put is "the remote destination file name", not directory name. So like this:
String remotePath = "/tmp/test.pdf";

Related

scp using Jsch to copy file asking for password

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.

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.

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.

How to write a string to a file located in remote server (linux)

I was trying to build an small code where I want to create some string and transfer that string to a file (that should be created in runtime) located in remote server. In my case the remote server is Linux.
Can someone help me here? I was using a JSCH and ChannelSftp but unable to do the thing. Below is my code:
JSch jsch = new JSch();
session = jsch.getSession(SFTPUSER, MachineIP, SFTPPORT);
String str = "Hello";
session.setPassword(SFTPPASS);
System.out.println(SFTPPASS);
java.util.Properties config = new java.util.Properties();
System.out.println("Config done");
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
System.out.println("Config set");
session.connect();
System.out.println("Session connected");
channel = session.openChannel("sftp");
channel.connect();
System.out.println("Connection Opened\n");
channelSftp = (ChannelSftp) channel;
channelSftp.cd(SFTPWORKINGDIR);
File f=new File("Test.txt");
//unable to do anything beyond this.
Sorry if you find this stupid but I am very new to it.
ChannelSftp has versions of the put method which accept a filename on the remote system and which return an OutputStream. Anything written to the OutputStream is written to the file on the remote system. You can write binary data to an OutputStream, or convert it to a Writer if you want to write text to it:
try (OutputStream out = channelSftp.put("/some/remote/file")) {
OutputStreamWriter writer = new OutputStreamWriter(out);
writer.write("some text");
} catch (IOException e) {
....
}
#Kenster answer doesn't work for me (get a 0 bytes file), so I gets another solution:
String content = "some text";
InputStream stream = new ByteArrayInputStream (content.getBytes ());
sftpChannel.put (stream, "/some/remote/file");
Hope it'll help somebody...

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