通过Powershell在Jenkins中使用AnsiColor

5

您好!有没有想过如何使用PowerShell在Jenkins上为输出着色?我已经在Jenkins上安装了AnsiColor插件,并设置了作业使用AnsiColor。唯一的问题是如何让我的PowerShell输出在Jenkins上显示颜色。

3个回答

6

我以前从未使用过它,所以我想试一试。基本上,您只需在字符串中直接输入转义字符(ASCII 27),然后是左括号[和代码,如此描述

为了使这更容易,我编写了一个格式化字符串的函数:

function Format-AnsiColor {
[CmdletBinding()]
[OutputType([String])]
param(
    [Parameter(
        Mandatory = $true,
        ValueFromPipeline = $true
    )]
    [AllowEmptyString()]
    [String]
    $Message ,

    [Parameter()]
    [ValidateSet(
         'normal display'
        ,'bold'
        ,'underline (mono only)'
        ,'blink on'
        ,'reverse video on'
        ,'nondisplayed (invisible)'
    )]
    [Alias('attribute')]
    [String]
    $Style ,

    [Parameter()]
    [ValidateSet(
         'black'
        ,'red'
        ,'green'
        ,'yellow'
        ,'blue'
        ,'magenta'
        ,'cyan'
        ,'white'
    )]
    [Alias('fg')]
    [String]
    $ForegroundColor ,

    [Parameter()]
    [ValidateSet(
         'black'
        ,'red'
        ,'green'
        ,'yellow'
        ,'blue'
        ,'magenta'
        ,'cyan'
        ,'white'
    )]
    [Alias('bg')]
    [String]
    $BackgroundColor
)

    Begin {
        $e = [char]27

        $attrib = @{
            'normal display' = 0
            'bold' = 1
            'underline (mono only)' = 4
            'blink on' = 5
            'reverse video on' = 7
            'nondisplayed (invisible)' = 8
        }

        $fore = @{
            black = 30
            red = 31
            green = 32
            yellow = 33
            blue = 34
            magenta = 35
            cyan = 36
            white = 37
        }

        $back = @{
            black = 40
            red = 41
            green = 42
            yellow = 43
            blue = 44
            magenta = 45
            cyan = 46
            white = 47
        }
    }

    Process {
        $formats = @()
        if ($Style) {
            $formats += $attrib[$Style]
        }
        if ($ForegroundColor) {
            $formats += $fore[$ForegroundColor]
        }
        if ($BackgroundColor) {
            $formats += $back[$BackgroundColor]
        }
        if ($formats) {
            $formatter = "$e[$($formats -join ';')m"
        }

       "$formatter$_"
    }
}

使用方法:

Format-AnsiColor -Message 'Hey there' -Style Bold -ForegroundColor Red

'Hello' | Format-AnsiColor -BackgroundColor Green

'One','Two','Three' | Format-AnsiColor -Style 'normal display' -ForegroundColor White -BackgroundColor Black

记住,如果您不再需要这个序列(我是指将样式和颜色设置回之前的状态),您必须关闭它。

这太美妙了 :) 它可以工作,但我需要将颜色设置回白色,这样我的 Jenkins 页面就不会保留我上次使用的颜色了吗? - fazlook1
@fazlook1 是的,你需要这样做。这些序列设置了颜色并没有将其还原,所以你需要自己处理。也许可以重新编写该函数以更好地解决这个问题。 - briantist
我会尽力自己编辑它。非常感谢,你让我的一天变得美好。哦等等......现在如果我从它自己的IDE运行PS,我会得到这些:[42mHello [0;37;43mOne [0;37;43mTwo [0;37;43mThree,我该如何解决? - fazlook1
@fazlook1 嗯...那就是这个函数的作用。如果没有解释序列,你会看到它们。你可以将此函数的输出分配给一个字符串,这样你就可以使用自己的逻辑来确定是否使用此函数,然后将你的(格式化或未格式化的)字符串发送到 Write-Host 或管道..这就是我现在能做的全部。 - briantist
我该如何使这个函数更加通用化?我只想要做到类似这样的效果:Format-AnsiColor "my message is here",默认颜色是红色。这可能吗? - fazlook1
1
@fazlook1 你可以保持函数不变,而是使用 $PSDefaultParameterValues(参考:https://technet.microsoft.com/zh-cn/library/hh847819.aspx),或者你可以在参数声明中为前景颜色赋一个默认值为红色:`$ForegroundColor = 'red'`。 - briantist

3

我在Jenkins中使用了很多长的PowerShell脚本,颜色是至关重要的! 我在Jenkins用户的profile.ps1文件中覆盖了原生的Write-Host函数。现在,所有我的本地脚本都可以在Jenkins上显示颜色。

function Write-Host {
    <#
        .SYNOPSIS
            Wrapper for Write-Host, adds ANSI SGR codes based on -foregroundColor and -backgroundColor
        .DESCRIPTION
            Renplace le Write-host standard, pour une compatibilité avec les sorties linux (JENKINS)
        .PARAMETER object
            Liste de String qui seront regroupe et affichée en couleur
        .PARAMETER foregroundColor
            Couleur du texte
        .PARAMETER backgroundColor
            Couleur de fond
        .PARAMETER nonewline
            si pas de retour a la ligne
        .NOTES
             Alban LOPEZ 2018
             alban.lopez@gmail.com
             http://git/PowerTech/
    #>
    param(
        $object,
        [ConsoleColor]$foregroundColor,
        [ConsoleColor]$backgroundColor,
        [switch]$nonewline
    )
        if (!(Get-Command Write-HostOriginal -ea 0).name){ # doit etre embarque (pour les scriptblock)
            $global:ConsoleOutput = ''
            $metaData = New-Object System.Management.Automation.CommandMetaData (Get-Command 'Microsoft.PowerShell.Utility\Write-Host')
            Invoke-Expression "function Global:Write-HostOriginal { $([System.Management.Automation.ProxyCommand]::create($metaData)) }"
        }

        # https://msdn.microsoft.com/en-us/library/system.consolecolor(v=vs.110).aspx
        # Converted to closest ANSI SGR equivalent
        $AnsiColor = [pscustomobject][ordered]@{ # doit etre embarque (pour les scriptblock)
            ForeGround = [pscustomobject][ordered]@{
                Black = 30
                Red = 91
                DarkRed = 31
                Green = 92
                DarkGreen = 32
                Yellow = 93
                DarkYellow = 33
                Blue = 94
                DarkBlue = 34
                Magenta = 95
                DarkMagenta = 35
                Cyan = 96
                DarkCyan = 36
                White = 97
                Gray = 37
                DarkGray = 90
            }
            BackGround = [pscustomobject][ordered]@{
                Black = 40
                White = 107
                Red = 101
                DarkRed = 41
                Green = 102
                DarkGreen = 42
                Yellow = 103
                DarkYellow = 43
                Blue = 104
                DarkBlue = 44
                Magenta = 105
                DarkMagenta = 45
                Cyan = 106
                DarkCyan = 46
                Gray = 47
                DarkGray = 100
            }
            style = [pscustomobject][ordered]@{
                RESET = 0
                BOLD_ON = 1
                ITALIC_ON = 3
                UNDERLINE_ON = 4
                BLINK_ON = 5
                REVERSE_ON = 7
                # BOLD_OFF = 22
                # ITALIC_OFF = 23
                # UDERLINE_OFF = 24
                # BLINK_OFF = 25
                # REVERSE_OFF = 27
            }
        }
        function Colorize-Text {
            <#
                .SYNOPSIS
                    Adds ANSI SGR codes to a string.
                .DESCRIPTION
                    Adds ANSI SGR codes to a string.
                .PARAMETER text
                    Text to be transformed.
                .PARAMETER ansiSgrCode
                    ANSI SGR number to insert.
                    See https://en.wikipedia.org/wiki/ANSI_escape_code for details
                    Or use the [AnsiColor] enum.

                    Also accepts an array of SGR numbers, and will apply all of them.
                .NOTES
                    Designed to play nicely with https://wiki.jenkins-ci.org/display/JENKINS/AnsiColor+Plugin
                .EXAMPLE
                    Colorize-Text 'toto' 7,93,101
            #>
            param(
                $object,
                [int[]]$ansiCodes #https://en.wikipedia.org/wiki/ANSI_escape_code#graphics
            )
            return "$([char]27)[$($ansiCodes -join(';'))m$object$([char]27)[0m"
        }

    $ansiCodes = @()

    if($style){
        $ansiCodes += $AnsiColor.style.$style
    }
    if($foregroundColor){
        $ansiCodes += $AnsiColor.ForeGround.$foregroundColor
    }
    if($backgroundColor) {
        $ansiCodes += $AnsiColor.BackGround.$backgroundColor
    }

    # Write-HostOriginal (Colorize-Text $object -ansiCodes $ansiCodes ) -nonewline # | Out-Host
    # (Colorize-Text $object -ansiCodes $ansiCodes ) | Out-Host
    # [Console]::Write( (Colorize-Text $object -ansiCodes $ansiCodes ) )
    if($foregroundColor -and $backgroundColor){
        # Write-HostOriginal (Colorize-Text $object -ansiCodes $ansiCodes ) -ForegroundColor $foregroundColor -BackgroundColor $backgroundColor -nonewline # | Out-Host
        $global:ConsoleOutput += (Colorize-Text $object -ansiCodes $ansiCodes )
    } elseif($foregroundColor){
        # Write-HostOriginal (Colorize-Text $object -ansiCodes $ansiCodes ) -ForegroundColor $foregroundColor -nonewline # | Out-Host
        $global:ConsoleOutput += (Colorize-Text $object -ansiCodes $ansiCodes )
    } elseif($backgroundColor){
        # Write-HostOriginal (Colorize-Text $object -ansiCodes $ansiCodes ) -BackgroundColor $backgroundColor -nonewline # | Out-Host
        $global:ConsoleOutput += (Colorize-Text $object -ansiCodes $ansiCodes )
    } else {
        # Write-HostOriginal $object -nonewline # | Out-Host
        $global:ConsoleOutput += $object
    }
    if (!$nonewline) {
        Write-HostOriginal $global:ConsoleOutput # -NoNewline
        $global:ConsoleOutput = ''
        # Write-HostOriginal '$!' -fore magenta 
    }
}

这段代码适用于线程和远程使用(Start-Job,Invoke-command)的ScriptBlock。


你好!感谢您提供这个不错的脚本!我不知道如何在Jenkins Powershell shell中使用这个脚本 :) “在我的Jenkins用户的profile.ps1文件中。”我该怎么做呢?谢谢! - sero
你好!以下代码无法正常工作:<code>Invoke-Command -ComputerName $nodeName -Authentication NegotiateWithImplicitCredential -ScriptBlock ${function:Set-WinServiceQC}</code> - sero

2

这是一个可替换 Write-Host 的工具,使用 ANSI 转义码 来渲染颜色。 可以在 CI 系统中输出彩色文本。

.Synopsis
    Write-Host but with ANSI colors!

.Description
    Drop-in Write-Host replacement that uses ANSI escape codes to render colors.
    Allows for colorized output in CI systems.

.Parameter Object
    Objects to display in the host.

.Parameter ForegroundColor
    Specifies the text color. There is no default.

.Parameter BackgroundColor
    Specifies the background color. There is no default.

.Parameter Separator
    Specifies a separator string to insert between objects displayed by the host.

.Parameter NoNewline
    The string representations of the input objects are concatenated to form the output.
    No spaces or newlines are inserted between the output strings.
    No newline is added after the last output string.

.Example
    Write-Host 'Double rainbow!' -ForegroundColor Magenta -BackgroundColor Yellow

.Notes
    Author : beatcracker (https://github.com/beatcracker)
    License: MS-PL (https://opensource.org/licenses/MS-PL)
    Source : https://github.com/beatcracker/Powershell-Misc
#>
function Write-Host {
    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipeline)]
        [Alias('Msg', 'Message')]
        [System.Object[]]$Object,
        [System.Object]$Separator,
        [System.ConsoleColor]$ForegroundColor,
        [System.ConsoleColor]$BackgroundColor,
        [switch]$NoNewline
    )

    Begin {
        # Map ConsoleColor enum values to ANSI colors
        # https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit
        $AnsiColor = @(
            30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97
        )
        # PS < 6.0 doesn't have `e escape character
        $Esc = [char]27
        $AnsiTemplate = "$Esc[{0}m{1}$Esc[{2}m"
    }

    Process {
        # https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_special_characters#escape-e
        # https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/wmf/whats-new/console-improvements#vt100-support
        if ($Host.UI.SupportsVirtualTerminal) {
            $Method = if ($NoNewline) { 'Write' } else { 'WriteLine' }
            $Output = if ($Separator) { $Object -join $Separator } else { "$Object" }

            # Splitting by regex ensures that this will work on files from Windows/Linux/macOS
            # Get-Content .\Foobar.txt -Raw | Write-Host -ForegroundColor Red
            foreach ($item in $Output -split '\r\n|\r|\n') {
                if ("$BackgroundColor") {
                    $item = $AnsiTemplate -f ($AnsiColor[$BackgroundColor.value__] + 10), $item, 49
                }
                if ("$ForegroundColor") {
                    $item = $AnsiTemplate -f $AnsiColor[$ForegroundColor.value__], $item, 39
                }

                [System.Console]::$Method($item)
            }
        }
        else {
            Microsoft.PowerShell.Utility\Write-Host @PSBoundParameters
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接