【问题标题】:Powershell as a java process on a unix system, output not displayed from cmdletPowershell作为unix系统上的java进程,cmdlet不显示输出
【发布时间】:2019-08-22 05:25:41
【问题描述】:

我正在为一个 powershell 客户端编写一个实现。这个实现是在java中。 JVM 在 UNIX 系统上运行。我需要能够创建一个对象PowerShellClient 并让它生成一个打开powershell 并允许我访问其stdin、stdout 和stderr 的进程,以便我可以在所述powershell 会话中调用命令并观察它们的输出。

我已经尝试过jpowershell,这个实现效果很好,但有一个限制:如果您尝试调用多次写入输出的cmdlet,则不会获得所有输出,并且不会完全读取输出。好像在第一个Write-Output之后就终止了

        PowerShell pwsh = PowerShell.openSession();
        String out = pwsh.executeCommand(
            "for($i=0; $i -lt 10; $i++){Write-Output $i; Start-Sleep -Seconds 1}")
            .getCommandOutput();

        System.out.println(out);

产生以下内容:

0

所以。我自己实现了一些东西,我决定以这样的方式实现它,它会等待提示 >>> 出现在 STDOUT 中。只有看到提示时才会停止读取,并允许执行另一个命令。但是,我已经有一个问题: 在标准输出中甚至看不到输出 powershell 对象的 cmdlet 输出。这是一些代码

import java.io.*;
import java.util.concurrent.Semaphore;

public class PowerShellClient {
    private PrintWriter stdin;
    private BufferedReader stderr;
    private BufferedReader stdout;
    private Process powerShellProcess;
    private Thread readErrThread;
    private Thread readOutThread;

    public PowerShellClient() throws IOException {
        powerShellProcess = new ProcessBuilder("powershell", "-nol", "-noe").start();

        stdout = new BufferedReader(
            new InputStreamReader(powerShellProcess.getInputStream()));

        stderr = new BufferedReader(
            new InputStreamReader(powerShellProcess.getErrorStream()));

        stdin = new PrintWriter(
            new OutputStreamWriter(
                new BufferedOutputStream(
                    powerShellProcess.getOutputStream())),
                    true);

        readOutThread = new Thread(() -> {
            String line;
            try {
                while ((line = stdout.readLine()) != null)
                    System.out.println("[STDOUT]: " + line);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        readErrThread = new Thread(() -> {
            String line;
            try {
                while(null != (line = stderr.readLine()))
                    System.out.println("[STDERR]: " + line);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        readErrThread.start();
        readOutThread.start();
    }

    public void executeCommand(String aRawCmd) {
        stdin.println(aRawCmd);
    }
}

以及用例:

PowerShellClient client = new PowerShellClient();
client.executeCommand("Get-Process");

产生以下内容:

[STDOUT]: >>> Get-Process
[STDOUT]: 
[STDOUT]: 

虽然这个用例:

PowerShellClient client = new PowerShellClient();
client.executeCommand("for($i=0; $i -lt 10; $i++) { Write-Output $i; Start-Sleep 1}");

产生以下内容:

[STDOUT]: >>> for($i=0; $i -lt 10; $i++) { Write-Output $i; Start-Sleep 1}
[STDOUT]: 0
[STDOUT]: 1
[STDOUT]: 2
[STDOUT]: 3
[STDOUT]: 4
[STDOUT]: 5
[STDOUT]: 6
[STDOUT]: 7
[STDOUT]: 8
[STDOUT]: 9

我的问题是这样的: 为什么会这样?是什么导致无法从通常产生 10 行输出的 cmdlet 中观察到输出?我认为这与 cmdlet 的输出被传递到 powershell 对象引擎这一事实有关,该引擎以某种方式确定终端的大小并格式化输出。我已经尝试过管道到Out-StringWrite-OutWrite-Host。我什至尝试将输出重定向到一个文件,然后cating 该文件。没有雪茄,文件没有内容(除了一个新的\n)。

我是否缺少一些配置或什么?

UNIX系统上安装的powershell版本: PowerShell 6.2.2

【问题讨论】:

  • 如果你想让 powershell 使用与 Java 相同的控制台,请使用 processBuilder.inheritIO(true),并且不要在 Java 中处理这 3 个流。
  • 你为什么要这样做? java 和 linux 上的 powershell 听起来很糟糕。
  • 用于自动化目的。我需要远程进入 Windows 机器以执行来自 Linux 环境的命令,来自 java 中的应用程序
  • 通过管道发送到Out-String 是否有效?
  • 不,这也不起作用。但是我能够解决问题。它在其他环境中不容易重现,解决方案是重新安装一些依赖项

标签: java powershell


【解决方案1】:

没有找到这个问题的根本原因,但我确实找到了解决方案。

解决办法是卸载powershell,重新安装几个依赖: omigssntlmsspkrb5-workstation

#! /bin/bash

#install pwsh
sudo curl https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/microsoft.repo
sudo yum install -y powershell

#get epel repository
cd /tmp
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install -y epel-release-latest-7.noarch.rpm

#install dependencies
sudo yum install -y omi gssntlmssp krb5-workstation

#restart omid
sudo systemctl restart omid

#create symlink for powershell
sudo ln -s /opt/microsoft/powershell/6/pwsh /usr/bin/powershell

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2017-11-18
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多