PowerShell和Java KeyTool – 抑制所有KeyTool输出

huangapple go评论72阅读模式
英文:

PowerShell and Java KeyTool - Suppress All KeyTool Output

问题

以下是翻译好的部分:

我正在为我的公司创建一个相对复杂的后构建脚本情境,它将处理许多不同的部分。使用PowerShell脚本提供了更大的灵活性,因此我已经开始学习它。
然而,在安装Java证书时存在输出重定向问题。

现在,一切都如预期运行。对于证书的检查,删除证书,甚至安装证书都很好,除了一个小问题:

(这是脚本成功运行的输出)

[命令:C:\Program Files\Java\jre1.8.0_261\bin\keytool.exe]
[参数:-list -storepass "storepass" -keystore "C:\Program Files\Java\jre1.8.0_261\lib\security\cacerts" -alias "ourcert.crt"]
[命令:C:\Program Files\Java\jre1.8.0_261\bin\keytool.exe]
[参数:-import -storepass "storepass" -keystore "C:\Program Files\Java\jre1.8.0_261\lib\security\cacerts" -alias "ourcert.crt" -file "\unc\drive\share\path\ourcert.crt" -noprompt]
证书已添加到密钥库 <-- 就是这一行
Java证书已安装到存储区。

我正在使用"&$Command $args"的方法来调用所有外部命令,以下是我运行的脚本。

此函数在许多地方用于简化KeyTool、Sonar Scanner和MSBuild的外部命令执行

function Invoke([String] $command, [String[]] $arguments)
{
Write-Host " [命令:$command]"
Write-Host " [参数:$arguments]"

&$command $arguments

}

function ValidateKeyTool()
{ # 我们的开发人员可能有可能没有相同版本的Java,因此这是为了在他们的系统上找到最新的版本
$path = [System.IO.Directory]::GetFiles("C:\Program Files (x86)\Java", "keytool.exe", [System.IO.SearchOption]::AllDirectories);
$path = $path + [System.IO.Directory]::GetFiles("C:\Program Files\Java", "keytool.exe", [System.IO.SearchOption]::AllDirectories);
$path = $path | Sort-Object -Descending;
$script:KeyTool = $path | Select -First 1;
$script:KeyStore = (Join-Path -Path (Split-Path (Split-Path $path)) -ChildPath "lib\security\cacerts");
return ([System.IO.File]::Exists($KeyTool) -and [System.IO.File]::Exists($KeyStore));
}

function CheckCertExists()
{
if (ValidateKeyTool)
{
$args = @("-list", "-storepass", ""storepass"", "-keystore", ""$KeyStore"", "-alias", ""ourcert.crt"");
Invoke $KeyTool $args | Out-Null;
return ($LastExitCode -eq 0)
}
else
{
throw "无法确定Java KeyTool或KeyStore";
}
}

function InstallCert()
{
if (!(CheckCertExists))
{
$args = @("-import", "-storepass", ""storepass"", "-keystore", ""$KeyStore"", "-alias", ""ourcert.crt"", "-file", $CertFile, "-noprompt");
Invoke $KeyTool $args | Out-Null; # 这个无法工作,Out-Null无法捕获输出
if ($LastExitCode -eq 0)
{
Write-Host " Java证书已安装到存储区。"
}
else
{
throw "尝试将Java证书安装到存储区时发生错误。"
}
}
else
{
Write-Host " Java证书已经安装。"
}
}

英文:

I am creating a somewhat complex Post-Build scripting situation for my company, which will handle many moving parts. Using Powershell scripting provides a greater flexibility and so I've begun learning it.
However there is a output redirect issue installing a Java Certificate.

Now, everything works as expected. The check for the cert, the delete cert, even the install cert works fine - except for one little issue:

(This is the output from a successful run of the script)

> [Command: C:\Program Files\Java\jre1.8.0_261\bin\keytool.exe]
> [Arguments: -list -storepass "storepass" -keystore "C:\Program Files\Java\jre1.8.0_261\lib\security\cacerts" -alias "ourcert.crt"]
> [Command: C:\Program Files\Java\jre1.8.0_261\bin\keytool.exe]
> [Arguments: -import -storepass "storepass" -keystore "C:\Program Files\Java\jre1.8.0_261\lib\security\cacerts" -alias "ourcert.crt" -file "\unc\drive\share\path\ourcert.crt" -noprompt]
> Certificate was added to keystore <-- This line here
> Java Cert Installed in Store.

I'm using the "&$Command $args" method of invoking all external commands, and below is the script I'm running.

# This function is used all over the place to streamline the external command execution of
# KeyTool, Sonar Scanner, and MSBuild
function Invoke([String] $command, [String[]] $arguments)
{  
	Write-Host &quot;    [Commnad:   $command]&quot;
	Write-Host &quot;    [Arguments: $arguments]&quot;

	&amp;$command $arguments
}

function ValidateKeyTool() 
{ # Our developers may or maynot have the same version of java so this is to find the most recent version on their system
    $path = [System.IO.Directory]::GetFiles(&quot;C:\Program Files (x86)\Java&quot;, &quot;keytool.exe&quot;, [System.IO.SearchOption]::AllDirectories);
    $path = $path + [System.IO.Directory]::GetFiles(&quot;C:\Program Files\Java&quot;, &quot;keytool.exe&quot;, [System.IO.SearchOption]::AllDirectories);
    $path = $path | Sort-Object -Descending;
    $script:KeyTool = $path | Select -First 1;
    $script:KeyStore = (Join-Path -Path (Split-Path (Split-Path $path)) -ChildPath &quot;lib\security\cacerts&quot;);
    return ([System.IO.File]::Exists($KeyTool) -and [System.IO.File]::Exists($KeyStore));
}


function CheckCertExists() 
{
    if (ValidateKeyTool) 
    {
        $args = @(&quot;-list&quot;, &quot;-storepass&quot;, &quot;&quot;&quot;storepass&quot;&quot;&quot;, &quot;-keystore&quot;, &quot;&quot;&quot;$KeyStore&quot;&quot;&quot;, &quot;-alias&quot;, &quot;&quot;&quot;ourcert.crt&quot;&quot;&quot;);
        Invoke $KeyTool $args | Out-Null;
        return ($LastExitCode -eq 0)
    }
    else 
    {
        throw &quot;Unable to determine Java KeyTool or KeyStore&quot;;
    }
}

function InstallCert()
{
    if (!(CheckCertExists))
    {
        $args = @(&quot;-import&quot;, &quot;-storepass&quot;, &quot;&quot;&quot;storepass&quot;&quot;&quot;, &quot;-keystore&quot;, &quot;&quot;&quot;$KeyStore&quot;&quot;&quot;, &quot;-alias&quot;, &quot;&quot;&quot;ourcert.crt&quot;&quot;&quot;, &quot;-file&quot;, $CertFile, &quot;-noprompt&quot;);
        Invoke $KeyTool $args | Out-Null;  #this DOESN&#39;T Work, the Out-Null doesn&#39;t trap the output
        if ($LastExitCode -eq 0) 
        {
            Write-Host &quot;  Java Cert Installed in Store.&quot;
        }
        else 
        {
            throw &quot;Error occured attempting to Install the Java Cert into the Store.&quot;
        }
    }
    else 
    {
        Write-Host &quot;  Java Cert already installed.&quot;
    }    
}

All executions of the KeyTool with the "| Out-Null" trap the output as expected, for -list, for -delete, but NOT for -import. No matter what I've tried, the keytool with "-import" always produces that "Certificate was added to keystore" output message. I want to suppress it, and only go off of the $LastExitCode for success/failure.

答案1

得分: 0

可能的原因是消息被输出到另一个输出流。例如,将消息输出到标准成功流(1)而不是标准错误流(2)或警告流(3)或其他流。管道传输到 | Out-Null 仅会处理成功流,例如:

PS C:\&gt; Write-Output &quot;hi&quot; | Out-Null
PS C:\&gt;
PS C:\&gt; Write-Warning &quot;hi&quot; | Out-Null
WARNING: hi

一种粗暴的方法是抑制所有流的所有消息,方法是这样重定向所有流,如下所示:

Invoke $KeyTool $args *&gt; $null

“更好的”方法是,如果您知道消息被发送到哪个流(例如错误流(2)),您可以重定向单独的流。方法是将错误流(2)重定向到成功流(1),然后将成功流(1)重定向到 $null

Invoke $KeyTool $args 2&gt;&amp;1 &gt; $null
英文:

Likely the cause is that the message is being outputted to another output stream. For ex. instead of outputting the message to the standard success stream (1), it may be outputting the message to the error stream (2) or warning stream (3), or another one. The pipelining to | Out-Null will only handle the success stream, e.g.:

PS C:\&gt; Write-Output &quot;hi&quot; | Out-Null
PS C:\&gt;
PS C:\&gt; Write-Warning &quot;hi&quot; | Out-Null
WARNING: hi

The blunt hammer approach to suppress all messages from all streams is to redirect all the streams like so:

Invoke $KeyTool $args *&gt; $null

The "nicer" approach is if you know which stream the message is being sent to, (for ex. the Error stream (2)), you can redirect the individual streams. You do this by redirecting the Error stream (2) to the Success stream (1), and then the Success stream (1) to $null:

Invoke $KeyTool $args 2&gt;&amp;1 &gt; $null

huangapple
  • 本文由 发表于 2020年10月21日 01:16:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/64450227.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定