2017-03-28 23 views
0

リモートマシンに接続してコマンドを実行するためのコードは次のとおりです。リモートマシンへの各Invoke-Command呼び出しに対して新しいセッションを作成すると動作します。 Invoke-Commandを使うたびに新しいセッションを作成したくないので、何百ものマシン上で何千ものコマンドに対して同時にスケーリングできず、セッション作成自体が大きなオーバーヘッドになります。リモートマシンへの複数のInvoke-Command呼び出しの$ session powershell変数で同じセッションオブジェクトを再利用できるようにする方法が必要です。Javaプログラムの中からPowerShellリモートセッションを作成する方法は?

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(); 
} 
} 

答えて

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でコマンドオブジェクトを形成する方法であると、あなたはこの実行してください:あなたが使用できるPSファイルをトリガするため

powershell -ExecutionPolicy Bypass -NoLogo -NoProfile -Command {Invoke-command ......} 

を - ファイルパススイッチ。

次のこれはそれを実行に役立ちます:

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(); 

は、それはあなたのセットを放つ願っています。

+0

私の要件は、単一のセッションを作成し、複数のコマンド/スクリプトを実行することです。上記のコードでは、すべての資格情報が渡されます。つまり、複数のセッションを作成しています。何らかの方法で資格情報を設定してから、複数のコマンド/スクリプトを実行できますか? – Manjur

+0

資格情報を渡すことができるセッション変数を作成し、そのセッション変数を利用して複数のスレッドを実行することができます –

関連する問題