Как создать удаленный сеанс PowerShell из Java-программы?
У меня есть следующий код для подключения к удаленному компьютеру и выполнения команд. Он работает, если я создаю новый сеанс для каждого вызова Invoke-Command с удаленного компьютера. Я не хочу создавать новый сеанс каждый раз, когда я использую Invoke-Command, так как он не будет масштабироваться для тысяч команд одновременно на сотнях машин, а создание самого сеанса - это большие издержки. Мне нужен способ, чтобы я мог повторно использовать один и тот же объект сеанса в переменной PowerShell $session для нескольких вызовов 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();
}
}
1 ответ
Видите, есть много логики, которая может помочь вам.
Ваш вызов сеанса в порядке; Но вы не можете напрямую запустить такую команду 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();
Надеюсь, это даст вам старт.
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();
}
}