如何从Java程序内部创建powershell远程会话?
我有下面的代码来连接到远程机器并执行命令。如果我为远程机器的每个调用命令调用创建一个新的会话,它就会工作。我不想每次使用Invoke命令时都创建一个新的会话,因为它不能在数百台机器上同时扩展数千个命令,而会话创建本身就是一个巨大的开销。我需要一种方法,以便可以重用$session powershell变量中的同一会话对象,以便对远程机器进行多个调用调用命令如何从Java程序内部创建powershell远程会话?,java,powershell,remoting,winrm,Java,Powershell,Remoting,Winrm,我有下面的代码来连接到远程机器并执行命令。如果我为远程机器的每个调用命令调用创建一个新的会话,它就会工作。我不想每次使用Invoke命令时都创建一个新的会话,因为它不能在数百台机器上同时扩展数千个命令,而会话创建本身就是一个巨大的开销。我需要一种方法,以便可以重用$session powershell变量中的同一会话对象,以便对远程机器进行多个调用调用命令 import java.io.BufferedReader; import java.io.IOException; import java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class PowerShellSession {
private static String subModule = "PowerShellSession";
String targetIpAddress;
String username;
String password;
public static Object connectPShellLock = new Object();
public PowerShellSession() {}
public void exec(String cmd, String credentials) {
String ex = "Invoke-Command -Session $session -ScriptBlock {" + cmd + "} -Computer " + targetIpAddress;
String[] args = new String[] { "powershell", ex};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
String command = "Exit-PSSession";
String[] args = new String[] { "powershell", command};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
private String getCredentials(String domain, String userName,
String password) throws IOException {
String creds = "$PlainPassword ='" + password
+ "'; $SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force;"
+ "$mycred = new-object -typename System.Management.Automation.PSCredential('" + userName + "', $SecurePassword);";
creds += "$session = New-PSSession -ComputerName " + domain + " -Credential $mycred;";
String[] args = new String[] { "powershell", creds};
execRemote(args);
return creds;
}
private void execRemote(String[] arguments) throws IOException {
ProcessBuilder builder = new ProcessBuilder(arguments);
builder.redirectErrorStream(true);
Process process = builder.start();
doProcessIO(process);
}
// Do the IO for a passed process
private void doProcessIO(Process p) throws IOException {
p.getOutputStream().close();
String line;
System.out.println("Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
p.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
p.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
// System.out.println("Done");
}
public static void main(String[] args) throws IOException {
PowerShellSession psSession = new PowerShellSession();
String credentials = psSession.getCredentials("9.120.241.195", "username", "password");
psSession.targetIpAddress = "9.120.241.195";
if(!credentials.equals("")) {
Scanner input = new Scanner(System.in);
while(true) {
System.out.print("PS C:\\Windows\\system32> ");
String cmd = input.nextLine();
if(cmd.equals("q") || cmd.equals("e") || cmd.equals("quit") || cmd.equals("exit")) break;
psSession.username = "username";
psSession.password = "password";
psSession.exec(cmd, "");
}
System.out.println("Finished PowerShell remote session.");
input.close();
}
psSession.close();
}
}
这里面有很多逻辑可以帮助你 您的会话调用很好;但是您不能直接运行这样的PS命令。您必须首先调用powershell.exe,然后为相应的远程命令指定要执行的命令 最后,您必须执行要准备的命令。让我与您分享一个示例代码:
public String executeScript(String psFileName, Systems system) throws NMAException {
Runtime runtime = Runtime.getRuntime();
String filePath = ApplicationProperties.getPropertyValue("powershell.scripts.location");
String command;
switch (psFileName) {
case "TerminalServersSystemInfo.ps1":
command = POWERSHELL + filePath + psFileName + " " + system.getPassword() + " " + system.getUserName()
+ " " + system.getSystemName();
break;
case "SQLServerInfo.ps1":
command = POWERSHELL + filePath + psFileName + " " + system.getSystemName() + " "
+ system.getUserName() + " " + system.getPassword();
break;
case "MyPS.ps1":
{
command = POWERSHELL + filePath + psFileName + " " + system.getSystemName() + " "
+ system.getUserName()
+ " " + system.getPassword() + " " + system.getDatabaseName();
break;
}
default:
throw new NMAException("not available");
}
以下是您应该如何在Java中形成command对象,然后执行以下操作:
powershell -ExecutionPolicy Bypass -NoLogo -NoProfile -Command {Invoke-command ......}
要触发PS文件,可以使用-Filepath开关
接下来,这将帮助您执行以下操作:
proc = runtime.exec(command);
proc.getOutputStream().close();
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
proc.getOutputStream().close();
LOGGER.info("Command: " + command);
LOGGER.info("Result:" + sb.toString());
return sb.toString();
我的要求是创建一个会话并执行多个命令/脚本。在上述代码中,在任何情况下都会传递凭据,这意味着我们正在创建多个会话。有没有办法让我只设置一次凭据,然后执行多个命令/脚本?您可以创建一个会话变量,在其中传递凭据,然后使用该会话变量运行多个会话threads@Manjur:我已经修改了您的代码,即第一个代码,现在现在开始工作了。
public class PowerShellSession {
private static String subModule = "PowerShellSession";
String targetIpAddress;
String username;
String password;
public static Object connectPShellLock = new Object();
public PowerShellSession() {}
public void exec(String cmd, String credentials) {
String ex = credentials +" Invoke-Command -ScriptBlock {" + cmd + "} -ComputerName " + targetIpAddress +" -Credential $mycred";
String[] args = new String[] { "powershell", ex};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
String command = "Exit-PSSession";
String[] args = new String[] { "powershell", command};
try {
execRemote(args);
} catch (IOException e) {
e.printStackTrace();
}
}
private String getCredentials(String domain, String userName,
String password) throws IOException {
String creds = "$Username = '"+userName+"';$PlainPassword ='" + password
+ "'; $SecurePassword = ConvertTo-SecureString -AsPlainText $PlainPassword -Force;"
+ "$mycred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword;";
//creds += "$session = New-PSSession -ComputerName " + domain + " -Credential $mycred;";
String[] args = new String[] { "powershell", creds};
execRemote(args);
return creds;
}
private void execRemote(String[] arguments) throws IOException {
ProcessBuilder builder = new ProcessBuilder(arguments);
builder.redirectErrorStream(true);
Process process = builder.start();
doProcessIO(process);
}
// Do the IO for a passed process
private void doProcessIO(Process p) throws IOException {
p.getOutputStream().close();
String line;
System.out.println("Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
p.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
p.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
System.out.println("Done");
}
public static void main(String[] args) throws IOException {
PropertiesFileReader propReader = new PropertiesFileReader(System.getProperty("user.dir")+"/cred.properties");
String user = propReader.getPropertyData("user");
String pass = propReader.getPropertyData("pass");
String ip_add = propReader.getPropertyData("ip");
PowerShellSession psSession = new PowerShellSession();
String credentials = psSession.getCredentials(ip_add, user, pass);
psSession.targetIpAddress = ip_add;//;
String cmdd = propReader.getPropertyData("command");//"Get-Culture";
if(!credentials.equals("")) {
psSession.exec(cmdd, credentials);
System.out.println("Finished PowerShell remote session.");
}
psSession.close();
}
}