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();
}
Related
I have a list of files for which I have to run the vimdiff command and save the output as a html file.I am doing this with Java. Below is the command I am trying to execute
String cmd = "vimdiff -c 'set foldlevel=9999' src/test/resources/testdata/output/html_output_before_changes/file1.html src/test/resources/testdata/output/html_output_after_changes/file2.html -c TOhtml -c 'w! different.html' -c 'qa!'"
When I run the below code, the code is getting executed. But I am not able to see the file getting generated.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmd);
The command is running fine when executed from a terminal. But its not working when executed inside a java program. Can someone help me with this issue? I did a lot of search but not able to proceed with this.
You're using :TOhtml and write the result as different.html. If you're not sure where to locate the file, check the current working directory of the Java process, do a file search of your hard disk, or specify an absolute path in the Vim command to be sure.
You won't see anything from Vim's operation itself. Using process.getInputStream(), you could obtain what Vim wrote to the terminal during its operation, but that would just amount to a garble of characters, as Vim is using special ANSI escape sequences to control the terminal, position the cursor, etc.
To use Vim non-interactively, it is recommended to pass the following options:
-T dumb Avoids errors in case the terminal detection goes wrong.
-n No swapfile.
-i NONE Ignore the |viminfo| file (to avoid disturbing the
user's settings).
-c 'set nomore' Suppress the more-prompt when the screen is filled
with messages or output to avoid blocking.
Without a possibility to interact with Vim (from inside your Java program), a troubleshooting tip is enabling verbose logging: You can capture a full log of a Vim session with -V20vimlog. After quitting Vim, examine the vimlog log file for errors.
After Two days I found the below Solution:
I added the vimdiff command to a shell script and executed it using the following method and it worked like a gem.
Java method
try {
File[] uiDiffDir = getFiles();
for (File file : uiDiffDir) {
String[] cmd = {"sh", shellScriptPath, file1, file2,
outputfile};
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
shell.sh
vimdiff -c 'set foldlevel=9999' $1 $2 -c TOhtml -c 'w! '"$3"'' -c 'qa!'
Note:
file1 will be passed as a argument in the place of $1
file2 will be passed as a argument in the place of $2
outputfile will be passed as a argument in the place of $3
I'm trying to use the WMIC command 'DESKTOP' in an application through a method which is implemented from an interface. Before using WMIC commands in cmd, it's necessary to first input 'WMIC' and press enter, as I'm sure you all know. I can do this just fine, however after the command line enters WMIC mode, I need to subsequently enter the DESKTOP command, or any other WMIC command (see list : http://ss64.com/nt/wmic.html). Here's the overridden method code I'm currently using to enter WMIC mode :
#Override
public void Desktop(){
try {
Runtime rt = Runtime.getRuntime();
String cmd = "cmd /c WMIC";
Process pr = rt.exec(cmd);
}
Perhaps I'm going about this the wrong way? Any help would be much appreciated.
You need to get the output stream of the process you started and write to it.
OutputStream os = pr.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("DESKTOP");
bw.newLine();
bw.flush();
If you need to see the output/errors from the process you started you need to use getInputStream() and getErrorStream() methods to get the output/error streams and read from it.
Check the javadoc of Process for more details.
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
Pay special attention to this part -
By default, the created subprocess does not have its own terminal or
console. All its standard I/O (i.e. stdin, stdout, stderr) operations
will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods getOutputStream(),
getInputStream(), and getErrorStream(). The parent process uses these
streams to feed input to and get output from the subprocess. Because
some native platforms only provide limited buffer size for standard
input and output streams, failure to promptly write the input stream
or read the output stream of the subprocess may cause the subprocess
to block, or even deadlock.
It's a fairly silly answer.
WMIC is normally used in non interactive mode.
wmic desktop get
However you are a programmer. Therefore you are supposed to program.
Here's vbs script that does it. The help is filled with sample scripts in C, VB, VBS, and JScript.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Desktop")
For Each objItem in colItems
msgbox objItem.Name & " " & objItem.Wallpaper
Next
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
I am trying to run following command in my Java program
Runtime.getRuntime().exec("ls -lrt service/logs/post/level2.log | awk '{print $9}'");
or
Runtime.getRuntime().exec("ls -lrt service/logs/post/level2* | awk '{print $9}'");
it gives me following error
ls: 0653-341 The file | does not exist.
ls: 0653-341 The file awk does not exist.
ls: 0653-341 The file '{print does not exist.
ls: 0653-341 The file $9}' does not exist.
Kindly help me
Pipes are a shell-based construct, not actual runnable commands. There are two options to do this as I see it:
Do the piping yourself within Java. Invoke the ls command first, get a handle to its OutputStream and then invoke awk connecting the first Process's output to the second Process' input stream.
Invoke the bash shell directly from Java, passing in the entire command as an argument to bash's -c parameter. That way all the piping is done within the single process.
As for the token-based errors, you should be invoking these commands with an array of strings; each element represents a token of the command line. So try, for example:
Runtime.getRuntime().exec(new String[] { "ls", "-lrt", "service/logs/post/level2.log" });
in order to invoke the ls command. I don't think this is strictly necessary in this case, but it will be for the awk command, since Java doesn't know anything about shell-specific quoting rules, so by default tokenises a single-string input on the space character. That's why your awk script was being split in two.
Edit (in response to comments): In the first option, I meant simply that you're able to pipe the output between the two processes yourself, in Java.
Imagine if you've created a process as so:
Process ls = Runtime.getRuntime().exec("ls -lrt service/logs/post/level2.log");
Now, this process will run and generate some output (which we know is going to be a line describing that file). We can get the stream for this output like so:
InputStream lsOut = ls.getInputStream();
Now, we want to run that awk process:
Process awk = Runtime.getRuntime().exec(new String[] { "awk", "{print $9}"});
The awk process of course will sit there are the moment waiting for input, since it knows it's going to be reading from stdin. So, we grab the input stream that it's going to be using:
OutputStream awkIn = awk.getOutputStream();
Now, the piping bit - we read the output of the ls command and pass it into the input for awk:
// TODO add buffering, error handling, probably run this in a separate thread
int datum = lsOut.read();
while (datum != -1)
{
awkIn.write(datum);
datum = lsOut.read();
}
This reads the output of ls (byte-by-byte for simplicity, using byte array buffers would be much faster but I'm trying to illustrate the concept simply) and writes it to the input of awk.
Then it's just a matter of reading the output from the awk process and dealing with it as you see fit.
I'm calling command line programs connected by pipes. All this works on Linux for sure.
My method:
protected String execCommand(String command) throws IOException {
String line = null;
if (command.length() > 0) {
Process child = Runtime.getRuntime().exec(command);
InputStream lsOut = child.getInputStream();
InputStreamReader r = new InputStreamReader(lsOut);
BufferedReader in = new BufferedReader(r);
String readline = null;
while ((readline = in.readLine()) != null) {
line = line + readline;
}
}
return line;
}
If I'm calling some cat file | grep asd, I'm getting the expected result. But not all commands works correctly. For example with this:
cat /proc/cpuinfo | wc -l
or this:
cat /proc/cpuinfo | grep "model name" | head -n 1 | awk -F":" '{print substr($2, 2, length($2))}
the method will return null. I'm guessing this problem depends on output formatting commands like head, tail, wc, etc. How I can work around this problem and get the final result of the output?
The pipe (like redirection, or >) is a function of the shell, and so execing directly from Java won't work. You need to do something like:
/bin/sh -c "your | piped | commands | here"
which executes a shell process with the command line (including pipes) specified after the -c (in quotes).
Note also that you have to consume stdout and stderr concurrently, otherwise your spawned process will block waiting for your process to consume the output (or errors). More info here.
Everyone who uses Runtime.exec should read this.
It might be a good idea to check the error stream of the Process as well.
Still didn't found proper solution to execute piped commands with Runtime.exec, but found a workaround. I've simply wrote these scripts to separate bash files. Then Runtime.exec calls these bash scripts and gets expected result.
The quick-and-dirty thing to do would be:
command = "/bin/sh -c '" + command.replaceAll("'", "'\''") + "'"
Normally, you'll have to watch out for shell injection (i.e. someone sneaks "; rm -rf /;" into the command). But that's only an issue if part of the command can be supplied from some other user input.
The slow and painful approach would be to do the Bash piping yourself in Java. If you go down this road, you'll find out all the wonderful things that Bash gives you that's not directly available from Process.exec (pipes, redirection, compound commands, variable expansion, arithmetic evaluation, ...).
Parse the command for | characters. Be sure to watch out for || and quoted strings.
Spawn a new Process for every piped command.
Create Threads that read the output from one command and write it to the input of the next command.
Probably a little too late but for others looking for a solution, try this...
String[] cmd = {
"/bin/sh",
"-c",
"cat /proc/cpuinfo | wc -l"
};
Process process = Runtime.getRuntime().exec(cmd);
All the best..