通过 powershell 在 jenkins 中使用 AnsiColor

Posted

技术标签:

【中文标题】通过 powershell 在 jenkins 中使用 AnsiColor【英文标题】:Use AnsiColor in jenkins via powershell 【发布时间】:2017-01-10 19:07:12 【问题描述】:

关于如何使用 powershell 为我在 Jenkins 上的输出着色有什么想法吗?我已经在我的 Jenkins 上安装了 AnsiColor 插件,并且我已经将作业设置为使用 AnsiColor。唯一的问题是如何让我的powershell在Jenkins上输出颜色。

【问题讨论】:

【参考方案1】:

使用ANSI escape codes 渲染颜色的插入式Write-Host 替换。 允许在 CI 系统中进行彩色输出。

Source
.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[0m1$Esc[2m"
    

    Process 
        # https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_special_characters#escape-e
        # https://docs.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
        
    

【讨论】:

【参考方案2】:

我在 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 中”。我怎么能做到这一点?谢谢! 您好!它不适用于:Invoke-Command -ComputerName $nodeName -Authentication NegotiateWithImplicitCredential -ScriptBlock $function:Set-WinServiceQC【参考方案3】:

好吧,我以前从未使用过它,所以我想我会尝试一下。基本上,您只需将转义字符 (ASCII 27) 后跟左括号 [,然后将代码 as described on this page 直接放入字符串中。

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

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

请记住,如果您不再需要它,则必须关闭序列(我的意思是将样式和颜色设置回原来的样子)。

【讨论】:

这太漂亮了 :) 它可以工作,但我需要将颜色设置回白色,这样我的 jenkin 页面就不会保留我使用的最后一种颜色吗? @fazlook1 是的。序列设置颜色并且不设置它,所以你必须自己做。可以编写该函数以更好地说明这一点。 我会尽力自己编辑。非常感谢你,你让我开心。哦等等......现在如果我从它自己的 IDE 运行 PS,我会得到这些:[42mHello [0;37;43mOne [0;37;43mTwo [0;37;43mThree],我该如何解决? @fazlook1 好吧.. 这就是函数的作用。如果没有什么可以解释序列,你会看到它们。您可以将此函数的输出分配给一个字符串,因此您可以使用自己的逻辑来确定是否使用此函数,然后将您的(格式化与否)字符串发送到Write-Host 或管道..仅此而已我现在可以做。 @fazlook1 你可以不理会函数和use $PSDefaultParameterValues,或者你可以在参数声明中将前景色的默认值指定为红色:$ForegroundColor = 'red' ,

以上是关于通过 powershell 在 jenkins 中使用 AnsiColor的主要内容,如果未能解决你的问题,请参考以下文章

持续集成~Jenkins里的powershell插件发布远程站点了

Jenkins中使用Azure Powershell连接Service Fabric报错not recognized的原因与解决办法

Jenkins powershell脚本中的转义空间和解析变量不起作用

Jenkins入门之执行Powershell脚本

Jenkins~powershell+cmd发布nuget包包

Jenkins在windows平台下,让Powershell批处理可以拉起进程并保持