我有以下代码连接到远程计算机并执行命令。如果我为远程计算机的每个Invoke-Command调用创建一个新会话,它正在工作。我不想在每次使用Invoke-Command时创建一个新会话,因为这不会同时扩展到数百台计算机上的数千个命令,而会话创建本身也是一个很大的开销。我需要一种方法,以便我可以在$ session powershell变量中重用相同的会话对象,以便对远程计算机进行多次Invoke-Command调用。
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();
}
}
答案 0 :(得分:2)
看到有很多逻辑涉及到这可以帮助你。
您的会话调用很好;但你不能直接运行这样的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中构建命令对象,然后执行此操作:
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();
希望它能让你出发。
答案 1 :(得分:0)
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();
}
}