I was doing some cmd commands via java that are only input in the command prompt.
I was wondering if there was a way to programatically fetch and reply to a command prompt question via Java?
e.g.: I add a remote GIT repository to my GIT structure locally, so when I execute:
$ git remote add [url],
I get prompted for a password. Can i catch this message (for example to pass the message to the user) AND reply in the same command prompt programming object/cmd window.
(the AND is explicitly in there because it would be useless to execute above command, read prompt reply, close command prompt, send password via a new cmd command in a new and thus non-related new prompt window).
If you are executing the command using Runtime.getRuntime().exec, capture/monitor the sub process's input stream and write to the output stream to send message to it.
E.g
Process process = Runtime.getRuntime().exec("Command ");
OutputStream pout = process.getOutputStream();
PrintWriter pw = new PrintWriter(pout);
pw.println("Command response here");
YOu can interact with the standard input / output / error streams of another command by using a ProcessBuilder to start that command as a Process. In that case, the process usually won't directly talk to a command window, so you'll have to print its output to the user if that is needed.
Note that some processes take particular care not to read passwords from standard input, but from the console window instead. In that case, the above might not work. Usually commands do provide some means to specify a different source for passwords. In the case of git, please search for the GIT_ASKPASS environment variable as well as the core.askpass configuration setting.
Related
I have been facing a strange issue in running scp command via my java application.
I am supposed to run this scp command with "-i" option where in ,I pass the identify key of a low privileged user(for an instance user B) while my java process is run by another logged in user(for an instance user A).
This is how my command looks in the application log when it's run by the logged in user "user A".
scp -l 10000 -o BatchMode=yes -o LogLevel=DEBUG -i "PathToIdentitykeyOfuserB" remoteUser#remoteHost:"PathToRemoteFile" "localPathofCopiedFile"
This command fails in my java application with errors saying
stdErr: Warning: Identity file not accessible: No such file or directory.
stdErr: remoteUser#remoteHost: Permission denied (publickey,password,keyboard-interactive).
what makes me wondering is the very same command runs perfectly, when it is run either in cygwin command line or windows command line.
I later added "-o LogLevel=DEBUG" in order to debug the internal logging for scp command to ascertain any difference in the logging informations of scp command itself (when it was run in windows cmd line) and when it is run via process builder of java application.
I observed that while SCP's(run through user A in windows command line)internal logging says it takes in the very same identity key of user B but its not this case when scp is run via process builder in my java application. Internal debug logging of SCP shows that it attempts to authenticate using the default private key of user A even after explicitly passing the identity key of user B.
Please find below few screenshots.
Identity key loaded in the SCP's internal logging from Windows CMD.
Authentication successful via Window CMD
Identity Key loaded in SCP's internal logging from process builder of java Application.
I fail to understand as to why SCP does not attempt to authenticate with the explicitly passed identity key of user B but rather tries to authenticate with its default identity key(user A).
However, its evident from the attached screenshots that from windows command line, it authenticates with the explicitly passed identity key and as a result, authentication succeeds.
I request experts to help me out with some tips to resolve this problem.
How can I make the process builder to take into account the identity key of passed identity key of another user instead of default key of user initiating it?
Any help would be greatly appreciated.
Here is how, I was creating process builder.
I have created a list of strings which basically holds scp command constructed with the list of strings and then pass this list directly as a parameter to command method of process builder.
I have managed to solve it now by creating a temporary file and then writing scp commands to it and run this temporary file in the process builder as against running scp command directly in the process builder earlier.
Instead of passing the list of strings which was used to construct scp command and passing the same to process builder, I have resorted to creating a temporary file and then writing scp command to it and lastly running this temporary file by passing to java process builder.
This solution seems to work now for me.
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.
I am trying to run a unix command from Java using java.lang.Process class.
How can we pass a specific user so that the command executes with the permissions of that specific user ?
I don't want to execute the command with a superuser.
You could use a ssh session, that logs with the user you know its password and run a specific command.
E.g. using java shell JSch
or
Expect4J
or
Ganymed-ssh-2
I found a good thread here by the way:
Jsch or SSHJ or Ganymed SSH-2?
You could start a login command first and then input credentials into it.
I would guess that starting su - [USER] should do the trick.
After reading through apropos user I came across the pkexec command which should do what you need.
You can run a new shell and execute commands which will switch to another user and then run the programm
I know there is a lot of thread about this problem but I dont found right: I follow this example: Want to invoke a linux shell command from Java to run command. Problem with ssh command is in authentication. When I run it I need to set password
$ ssh root#server 'fgrep Exception *.log*'
Enter passphrase for key '/././.ssh/id_rsa':
How can I pass here password ?
There are libraries are available to invoke ssh. The Java Secure Channel (JSCH) is a very popular library, used by maven, ant and eclipse. It is open source with a BSD style license.
If you need authentication for ssh, you can use through java.
If your still need to by pass password passing, there are two ways to do what you want. One involves a stored password, and one does not.
Both are non-interactive, meaning that they can work when you're not there to enter a password.
The way that does not require a password. You can use public/private
key authentication instead of passwords with SSH. I'm going to
assume that you're using OpenSSH, which comes with practically every
Linux distribution.
Steps :
Configure your SSH server to accept private key logins. In /etc/ssh/sshd_config make sure that there's a line that says PubkeyAuthentication yes (and that there is no # infront of it). If you change this file, you need to restart the sshd service.
On your local machine (not the server), create yourself a pair of keys with ssh-keygen -t rsa (you can use other options than rsa, but I'm keeping it simple). Do not specify a password. Save the keys in the locations prompted.
Open the contents of the id_rsa.pub file that you just created (it's one very long line of text), and copy the contents into the end of the file $HOME/.ssh/authorized_keys on the server machine. Create the file if it doesn't exist.
Further Detail refer here.
The basic idea is to use expect, which is an
administration automation tool, to type your password in to ssh when
prompted. It might not always work, and when it doesn't, it's hard
to figure out why not. I recommend the first method.
Anyway, here's a command that you can poke at until it does what you
want.
The script Code is:
expect -c 'spawn ssh user#remote.host ; expect assword ; send "passphrase\n" ; interact'
Expect might not be installed on your system. Make sure install that
You need to get the InputStream (which has the output) from the execution and wait for it to ask you for the password, then get the OutputStream (into which you give the command its input) and send it the password you want.
Have a read of this article