When I connect to SSH using PuTTY, I get the following message as given below.
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-98-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
deb#ubuntu:~$
Similarly, when I use JSch library to connect, I should also get the same message in Java. Please help me about how to get this. I provide below my code details.
public String connect() {
String errorMessage = null;
try {
sesConnection = jschSSHChannel.getSession(userName, ipOrHostName, PORT);
sesConnection.setPassword(password);
sesConnection.setConfig("StrictHostKeyChecking", "no");
sesConnection.connect(TIMEOUT);
//After connecting, I should get the welcome message
} catch (JSchException jschX) {
errorMessage = jschX.getMessage();
}
return errorMessage;
}
I want to get the welcome message from a unix system before executing the commands in JSch. Please help about how to get it.
The message you are seeing is simply printed on a shell output.
That does not go well with automatic its reading and executing commands.
I general to automate a command execution, you correctly plan to use SSH channel "exec" (ChannelExec in JSch). But that channel won't give you the message.
You would have to use "shell" channel (ChannelShell in JSch). But that channel is intended for implementing an interactive shell session. Not to automate command execution and not for parsing command output. Particularly in the context of your question, there's no realiable way to find out the end of the "welcome message". You would have to read the output line by line, until you get the prompt ("deb#ubuntu:~$").
Or, if your use case allows that, you can use ChannelShell to get the message and then use ChannelExec to execute the commands.
You better talk to the server administrator to make the information you need available using a different API (like using SSH2_MSG_USERAUTH_BANNER, or even other way).
See my answer to SSH MOTD per user to understand the different ways how the server can provide the "welcome message". Had the server used SSH2_MSG_USERAUTH_BANNER, you could use UserInfo.showMessage to capture the message. See also How to read the SSH key-sig pair banner (for generating SSH password) after connecting to host in Java?
Related
I am trying to connect to a local ssh for testing purposes.
I am trying to login using ssh keys with jsch.
This is what I am putting in config:
config.put(STRICT_HOST_KEY_CHECK, strictHostKeyCheckValue); // no
config.put("PreferredAuthentications", "publickey");
The keys are valid and I am passing in the correct path to them.
The sever is running in background.
But I am not able to connect to it.
The error is “Auth failed”.
Can anyone suggest where should I look further.
I am working on macos.
I've never used ssh where the client and server are the same host, but I just tried. The server STILL uses ~/.ssh/authorized_keys to look for the public key. IS it there? Make sure with cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys. That at least is what my public key file is. Yours might be different.
I would like to know how to create a file / directory in remote machine using Java11 ?
I did try to use:
process = Runtime.getRuntime()
.exec("ssh root#" + hostname + " 'mkdir -p "+mdbDir+"'")
.wait() or waitFor();
But i am getting an exception even though i use wait()
java.lang.IllegalThreadStateException: process has not exited
Please let me know what can be done.
You should only call Process.waitFor() without Process.wait(). Object.wait is about synchronization. It has nothing to do with process management.
You have a good example here about how to use an SSHClient from sshj, more specific for the task that you want to do:
Send ssh command from Java code
Moreover, you will probably need a trusted connection with the target server. Check if an SSH connection from your system requires a password, if your system and the server has a trusted connection it will no ask for the password.
If you still want to use your approach without a library I guess that the problem is that the execution is waiting for some input like adding the host to the knowhosts or the password, and that is the reason for the process not exiting.
I am using JSch in a Java client to connect to a remote server and get some files using SFTP. The following code has been working fine for me: -
JSch ssh = new JSch();
JSch.setConfig(FileTransferConstants.STRICT_HOST_KEY_CHECKING, FileTransferConstants.NO);
Session session = ssh.getSession(userName, host, port);
session.setPassword(password);
session.connect();
Channel channel = session.openChannel(FileTransferConstants.SFTP);
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
sftp.cd(remoteDirectoryPath);
sftp.lcd(localDirectoryPath);
sftp.get(remoteDirectoryPath + remoteFileName, remoteFileName);
The problem is that there has now been a change of site policy. I am no longer permitted to log on directly as this user (userName above). I must first log on as my personal user and then su into the user that has access to the files I want to SFTP.
I don't think there is anyway I can refactor the above code to achieve this and so I have started looking at using a shell or exec channel instead. I have had little success so far and cannot seem to find any examples on the web, so I would be very grateful for any advice or pointers in the right direction. Many thanks.
I do not think you can do this directly with JSch. But with some modification of its code, it's probably doable.
Note that my answer assumes that the server is *nix-based (what is backed by your reference to su) and uses OpenSSH SFTP server.
You have to open SSH "exec" channel, to execute something like:
sudo /bin/sftp-server
But on top of that channel, you need to build the ChannelSftp instance, not ChannelExec.
So you will need to implement Session.openChannel-like method, that will open exec channel, but create ChannelSftp for it.
For some background, see how it's possible to do sudo with WinSCP SFTP client.
Note that while the FAQ claims, that you won't be able to use password for the sudo, that's true for WinSCP. But as you have a full control of the session with JSch, you may be able to feed the password to sudo.
For that you might override the ChannelSftp.start() to write the password to the channel input, before starting the actual SFTP session.
You still need the requiretty option be off, as the SFTP cannot work with TTY.
For general considerations when automating operations using a different/root account, see:
Allowing automatic command execution as root on Linux using SSH
Currently when I connect from windows to our linux host server, I use putty with my credentials in a .bat file to automatically access the machine. However the connection does not automatically direct me to the terminal shell but there's a secondary interactive login prompt that requires me to manually input another username and password, as of now I don't know how to get pass these with automation.
My question, is it possible to automate these specifically on java or just a .bat?
One of my co-workers managed to do it on VB script using the "sendkey" method. The information online states "sendkey" send one or more keystrokes to the active window as if they were typed at the keyboard. May I know is there a counterpart of sendkey in Java in JSCH or SSHJ?
NOTE: I'm not after to connect directly to the terminal, what I'm after is to automate the interactive login as if I were manually typing it like what the sendkey does.
Injecting typed characters into a ssh session is pretty simple. Just inject the characters to be written into the OutputStream provided by sshj. I assume that you log-in and then execute something that requires the interactive console login.
I simulate the executed process using the following simple script named test.sh. It reads a typed line and prints it.
#/bin/bash
read varname
echo You typed $varname
I am executing this script using a modified Exec example from sshj:
final Session session = ssh.startSession();
try {
Command cmd = session.exec("/home/username/test.sh");
OutputStream out = cmd.getOutputStream();
out.write("1234567\n".getBytes()); // we type 1234567
out.flush();
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
System.out.println("\n** exit status: " + cmd.getExitStatus());
} finally {
session.close();
}
If you execute the script using the sshj code you will get the result
You typed 1234567
By reading the inputStream line by line you can wait for the line that asks for the username or password and send the right data to the server, simulating your input.
I'm trying to execute a SH script from my java GUI application. I'm using jsch to connect to the machine.
I can execute commands like "ls" or "pwd". When I try to execute my SH I only get all output from it, if I execute it directly in the machine it take several time (that's what is expected) and works fine.
The script begins with
"#!/bin/bash"
and the code that call it is:
String command= "cd /opt/app/ordersync/scripts/RE-INJEC;sh ./proc_reinjec.sh"; // enter any command you need to execute
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
in = channel.getInputStream();
channel.connect();
When I execute it
I get TERM environment variable not set
I can't figure it out what is the problem. I tried to the same in php with shell_exec and I the problem (result) was the same.
This is only a guess. So consider that mostly as a (long) comment. But you are assuming your "command" will in fact be parsed by an intermediate shell, that might even be responsible to set a proper environment. But, does ChannelExec really launch a shell? Or does it instead execute directly the command?
Anyway, try that:
String command= "sh -l -c 'cd /opt/app/ordersync/scripts/RE-INJEC;sh ./proc_reinjec.sh'";
// ^^^^^^^^^^ ^
// explicit sub-shell don't forget the closing quote >-->-->----/
// '-l' is for login shell: reads /etc/profile, ... at startup
// I don't know if this is required here
But maybe in fact you are searching for ChannelShell instead?
From RFC 4254, section 6.5. Starting a Shell or a Command:
6.5. Starting a Shell or a Command
Once the session has been set up, a program is started at the
remote end. The program can be a shell, an application program, or
a subsystem with a host-independent name. Only one of these
requests can succeed per channel.
byte SSH_MSG_CHANNEL_REQUEST
uint32 recipient channel
string "shell"
boolean want reply
This message will request that the user's default shell (typically
defined in /etc/passwd in UNIX systems) be started at the other end.
byte SSH_MSG_CHANNEL_REQUEST
uint32 recipient channel
string **"exec"**
boolean want reply
string command
This message will request that the server start the execution of
the given command. The 'command' string may contain a path.
Normal precautions MUST be taken to prevent the execution of
unauthorized commands.