Strange behavior while running remote powershell execution from Java - java

I have a Windows server with WSUS and I am trying to activate some powershell script sitting on that machine.
First of all, the script works when I am trying to activate it via power shell admin shell.
The script looks like this :
Enable-PSRemoting
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force
$secpasswd = ConvertTo-SecureString "p#`$`$w0rd" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ("1.1.2.3\administrator", $secpasswd)
$s = New-PSSession -ComputerName 1.1.2.3 -Credential $creds
Invoke-Command -Session $s -Scriptblock {Get-Hotfix}
I am using 2 different approach via Java :
public static void run2() throws IOException {
Runtime runtime = Runtime.getRuntime();
Process proc = new ProcessBuilder()
.inheritIO()
.command("powershell", "invoke-command",
"-Computer", "1.1.2.3",
"-Scriptblock" ,"{&C:\\install-patch-ocomputer.ps1}").start();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
reader.close();
proc.getOutputStream().close();
}
public static void run6() throws IOException {
Runtime runtime = Runtime.getRuntime();
BufferedReader reader = null;
Process proc = runtime.exec("powershell Invoke-Command -Computer 1.1.2.3 -Scriptblock {&C:\\install-patch-computer.ps1}");
try {
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e){
e.printStackTrace();
} finally {
reader.close();
proc.getOutputStream().close();
}
}
When I am running run2 method I get :
[1.1.2.3] Connecting to remote server 1.1.2.3 failed with the following error message : The WinRM client
cannot process the request. Default authentication may be used with an IP address under the following conditions: the
transport is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use
winrm.cmd to configure TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated. For more
information on how to set TrustedHosts run the following command: winrm help config. For more information, see the
When running run6 :
No error, but no output from script as well...
Please help !!!!

Related

Using Runtime.getRuntime().exec with multiple parameters

So I trying to use Runtime.getRuntime().exec to execute a openview command from Java code. This exact command runs fine on command prompt on the server does the necessary updates, but fails to perform when executed through Java code. The issue is that it returns exit status code of success i,e "0" when invoked through Java, but doesn't performs the updates it is suppose to do (appears like it is not executing).
Here is the command :
opcmsg application='Tester Down 11' object='My Support' severity=minor msg_grp='MyGroup' msg_text='DEV: -m=New Details:Request Detail description'
Here is the code :
String[] command = {
"opcmsg",
"application=\'Tester Down 11\'",
"object=\'My Support\'",
"severity=minor",
"msg_grp=\'MyGroup\'",
"msg_text=\'DEV: -m=New Details:Request Detail description\'"
}
p = Runtime.getRuntime().exec(command);
InputStream stderr = p.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String errorDescription = null;
while ( (errorDescription = br.readLine()) != null)
LOGGER.info(errorDescription);
exitStatus = p.waitFor();
LOGGER.info("exitStatus : " + exitStatus);
This worked :
String[] command = { "/bin/sh",
"-c",
"opcmsg application=\'Tester Down 11\' object=\'My Support\' severity=minor msg_grp=\'MyGroup\' msg_text=\'DEV: -m=New Details:Request Detail description\' " }

How stop a service and its dependencies via cmd with java?

I tested with net stop \\ComputerName "NPS Index", but displays:
The syntax of this command is:
NET STOP
service
The service has dependencies.
The java code is:
private static void stopService(String server, String serviceName) {
try {
// ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "sc", "\\\\" + server, "stop", serviceName);
// Process process = builder.start();
// process.waitFor();
String[] command = {"cmd.exe", "/c", "net", "\\\\" + server, "stop" , serviceName};
Process process = new ProcessBuilder(command).start();
InputStream inputStream = process.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
Thread.sleep(3000);
} catch (Exception e) {
log.error("Error to execute commands line in cmd " + e);
}
}
please, somebody could help me?
Are you trying to stop a service on a remote computer?
In this case the syntax is
sc \\machine stop <service>
(see How do I restart a service on a remote machine in Windows?)
You can list the service dependencies with the --EnumDepend flag.

Invoke Powershell scripts from Java

I want to invoke my powershell script from java. Can it be done. I tried with the following code, but the stream is not closing.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class TestPowershell {
public static void main(String[] args) throws IOException
{
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("powershell C:\\testscript.ps1");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
reader.close();
proc.getOutputStream().close();
}
}
Does java invoke a powershell script which performs create remote session and execute cmdlets?
Do we have support to invoke powershell scripts in java?
Anyone could you please help on this.
Awaiting for your responses.
Thanks,
rammj
After starting the process ( runtime.exec() ), add a line to close the input stream of the process ( which JAVA calls output stream!!):
proc.getOutputStream().close();
Now you can do it easily with jPowerShell
powerShell = PowerShell.openSession();
//Print results
System.out.println(powerShell.executeScript("\"C:\\testscript.ps1\"").getCommandOutput());
powerShell.close();
Yes we can create remote session and execute cmdlets using powershell script.
Save the following Power shell script to testscript.ps1
#Constant Variables
$Office365AdminUsername="YOUR_USERNAME"
$Office365AdminPassword="TOUR_PASSWORD"
#Main
Function Main {
#Remove all existing Powershell sessions
Get-PSSession | Remove-PSSession
#Encrypt password for transmission to Office365
$SecureOffice365Password = ConvertTo-SecureString -AsPlainText $Office365AdminPassword -Force
#Build credentials object
$Office365Credentials = New-Object System.Management.Automation.PSCredential $Office365AdminUsername, $SecureOffice365Password
Write-Host : "Credentials object created"
#Create remote Powershell session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $Office365credentials -Authentication Basic –AllowRedirection
Write-Host : "Remote session established"
#Check for errors
if ($Session -eq $null){
Write-Host : "Invalid creditials"
}else{
Write-Host : "Login success"
#Import the session
Import-PSSession $Session
}
#To check folder size
Get-MailboxFolderStatistics "YOUR_USER_NAME" | Select Identity, FolderAndSubfolderSize
exit
}
# Start script
. Main
Java Code :
try {
String command = "powershell.exe \"C:\\testscript.ps1\"";
ExecuteWatchdog watchdog = new ExecuteWatchdog(20000);
Process powerShellProcess = Runtime.getRuntime().exec(command);
if (watchdog != null) {
watchdog.start(powerShellProcess);
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(powerShellProcess.getInputStream()));
String line;
System.out.println("Output :");
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
If you do not get output, try this: powerShellProcess.getErrorStream() instead powerShellProcess.getInputStream(). It will show the errors.

How do I run multiple commands in SSH through Java?

How do I run multiple commands in SSH using Java runtime?
the command: ssh user#127.0.0.1 'export MYVAR=this/dir/is/cool; /run/my/script
/myscript; echo $MYVAR'
#Test
public void testSSHcmd() throws Exception
{
StringBuilder cmd = new StringBuilder();
cmd.append("ssh ");
cmd.append("user#127.0.0.1 ");
cmd.append("'export ");
cmd.append("MYVAR=this/dir/is/cool; ");
cmd.append("/run/my/script/myScript; ");
cmd.append("echo $MYVAR'");
Process p = Runtime.getRuntime().exec(cmd.toString());
}
The command by its self will work but when trying to execute from java run-time it does not. Any suggestions or advice?
Use the newer ProcessBuilder class instead of Runtime.exec. You can construct one by specifying the program and its list of arguments as shown in my code below. You don't need to use single-quotes around the command. You should also read the stdout and stderr streams and waitFor for the process to finish.
ProcessBuilder pb = new ProcessBuilder("ssh",
"user#127.0.0.1",
"export MYVAR=this/dir/is/cool; /run/my/script/myScript; echo $MYVAR");
pb.redirectErrorStream(); //redirect stderr to stdout
Process process = pb.start();
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while((line = reader.readLine())!= null) {
System.out.println(line);
}
process.waitFor();
If the Process just hangs I suspect that /run/my/script/myScript outputs something to stderr. You need to handle that output aswell as stdout:
public static void main(String[] args) throws Exception {
String[] cmd = {"ssh", "root#localhost", "'ls asd; ls'" };
final Process p = Runtime.getRuntime().exec(cmd);
// ignore all errors (print to std err)
new Thread() {
#Override
public void run() {
try {
BufferedReader err = new BufferedReader(
new InputStreamReader(p.getErrorStream()));
String in;
while((in = err.readLine()) != null)
System.err.println(in);
err.close();
} catch (IOException e) {}
}
}.start();
// handle std out
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader reader = new BufferedReader(isr);
StringBuilder ret = new StringBuilder();
char[] data = new char[1024];
int read;
while ((read = reader.read(data)) != -1)
ret.append(data, 0, read);
reader.close();
// wait for the exit code
int exitCode = p.waitFor();
}
The veriant of Runtime.exec you are calling splits the command string into several tokens which are then passed to ssh. What you need is one of the variants where you can provide a string array. Put the complete remote part into one argument while stripping the outer quotes. Example
Runtime.exec(new String[]{
"ssh",
"user#127.0.0.1",
"export MYVAR=this/dir/is/cool; /run/my/script/myScript; echo $MYVAR"
});
That's it.
You might want to take a look at the JSch library. It allows you to do all sorts of SSH things with remote hosts including executing commands and scripts.
They have examples listed here: http://www.jcraft.com/jsch/examples/
Here is the right way to do it:
Runtime rt=Runtime.getRuntime();
rt.exec("cmd.exe /c start <full path>");
For example:
Runtime rt=Runtime.getRuntime();
rt.exec("cmd.exe /c start C:/aa.txt");
If you are using SSHJ from https://github.com/shikhar/sshj/
public static void main(String[] args) throws IOException {
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
ssh.connect("10.x.x.x");
try {
//ssh.authPublickey(System.getProperty("root"));
ssh.authPassword("user", "xxxx");
final Session session = ssh.startSession();
try {
final Command cmd = session.exec("cd /backup; ls; ./backup.sh");
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
System.out.println("\n** exit status: " + cmd.getExitStatus());
} finally {
session.close();
}
} finally {
ssh.disconnect();
}
}

Why ulimit returns different results through java Runtime.exec()

why the 'ulimit -a' returns differently through Runtime.exec() from running it straight under bash, thanks for any pointers.
Java:
open files (-n) 65536
bash-3.00$ ulimit -a:
open files (-n) 256
public class TestUlimit {
public TestUlimit() throws IOException, InterruptedException {
Runtime runTime = Runtime.getRuntime();
Process p = runTime.exec(new String[] { "bash", "-c", "ulimit -a" });
InputStream in = p.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("Result of Process p = runTime.exec(new String[] { \"bash\", \"-c\", \"ulimit -a\" });");
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
p = runTime.exec("ulimit -a");
in = p.getInputStream();
isr = new InputStreamReader(in);
br = new BufferedReader(isr);
System.out.println("Result of p = runTime.exec(\"ulimit -a\");");
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
}
bash executes a ulimit command of its own? Check .profile, .bashrc, etc.
ulimit is a shell builtin and its default values are based on the configuration of the shell. It's possible that Java's using a default shell other than bash. Even if that's not the case, it could be that you have some settings in, for example, .profile that are invoked when you've got a command line but not when running the shell programmatically.

Categories