Detect and correct PowerShell mishandling nssm Unicode output as UTF8 (#2867)

* extra detail on which step triggered 'change', detect and handle powershell mishandling nssm's unicode as utf8

* Simpler handling of nssm output encoding

Thanks @nitzmahone for a cleaner way to control PowerShell's behavior
This commit is contained in:
Jason Ritchie 2016-11-11 13:40:37 -05:00 committed by Matt Clay
parent 54c5ebf697
commit 0f6aa07d88

View file

@ -42,6 +42,33 @@ $dependencies = Get-Attr $params "dependencies" -default $null
$user = Get-Attr $params "user" -default $null
$password = Get-Attr $params "password" -default $null
#abstract the calling of nssm because some PowerShell environments
#mishandle its stdout(which is Unicode) as UTF8
Function Nssm-Invoke
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$cmd
)
Try {
$encodingWas = [System.Console]::OutputEncoding
[System.Console]::OutputEncoding = [System.Text.Encoding]::Unicode
$nssmOutput = invoke-expression "nssm $cmd"
return $nssmOutput
}
Catch {
$ErrorMessage = $_.Exception.Message
Fail-Json $result "an exception occurred when invoking NSSM: $ErrorMessage"
}
Finally {
# Set the console encoding back to what it was
[System.Console]::OutputEncoding = $encodingWas
}
}
Function Service-Exists
{
[CmdletBinding()]
@ -63,11 +90,11 @@ Function Nssm-Remove
if (Service-Exists -name $name)
{
$cmd = "nssm stop ""$name"""
$results = invoke-expression $cmd
$cmd = "stop ""$name"""
$results = Nssm-Invoke $cmd
$cmd = "nssm remove ""$name"" confirm"
$results = invoke-expression $cmd
$cmd = "remove ""$name"" confirm"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -76,6 +103,7 @@ Function Nssm-Remove
Throw "Error removing service ""$name"""
}
Set-Attr $result "changed_by" "remove_service"
$result.changed = $true
}
}
@ -101,9 +129,7 @@ Function Nssm-Install
if (!(Service-Exists -name $name))
{
$cmd = "nssm install ""$name"" $application"
$results = invoke-expression $cmd
$results = Nssm-Invoke "install ""$name"" $application"
if ($LastExitCode -ne 0)
{
@ -112,11 +138,11 @@ Function Nssm-Install
Throw "Error installing service ""$name"""
}
Set-Attr $result "changed_by" "install_service"
$result.changed = $true
} else {
$cmd = "nssm get ""$name"" Application"
$results = invoke-expression $cmd
$results = Nssm-Invoke "get ""$name"" Application"
if ($LastExitCode -ne 0)
{
@ -125,11 +151,11 @@ Function Nssm-Install
Throw "Error installing service ""$name"""
}
if ($results -ne $application)
if ($results -cnotlike $application)
{
$cmd = "nssm set ""$name"" Application $application"
$cmd = "set ""$name"" Application $application"
$results = invoke-expression $cmd
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -137,7 +163,9 @@ Function Nssm-Install
Set-Attr $result "nssm_error_log" "$results"
Throw "Error installing service ""$name"""
}
Set-Attr $result "application" "$application"
Set-Attr $result "changed_by" "reinstall_service"
$result.changed = $true
}
}
@ -184,8 +212,8 @@ Function Nssm-Update-AppParameters
[string]$appParameters
)
$cmd = "nssm get ""$name"" AppParameters"
$results = invoke-expression $cmd
$cmd = "get ""$name"" AppParameters"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -228,11 +256,11 @@ Function Nssm-Update-AppParameters
{
if ($appParameters)
{
$cmd = "nssm set ""$name"" AppParameters $singleLineParams"
$cmd = "set ""$name"" AppParameters $singleLineParams"
} else {
$cmd = "nssm set ""$name"" AppParameters '""""'"
$cmd = "set ""$name"" AppParameters '""""'"
}
$results = invoke-expression $cmd
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -241,11 +269,12 @@ Function Nssm-Update-AppParameters
Throw "Error updating AppParameters for service ""$name"""
}
Set-Attr $result "changed_by" "update_app_parameters"
$result.changed = $true
}
}
Function Nssm-Set-Ouput-Files
Function Nssm-Set-Output-Files
{
[CmdletBinding()]
param(
@ -255,8 +284,8 @@ Function Nssm-Set-Ouput-Files
[string]$stderr
)
$cmd = "nssm get ""$name"" AppStdout"
$results = invoke-expression $cmd
$cmd = "get ""$name"" AppStdout"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -265,16 +294,16 @@ Function Nssm-Set-Ouput-Files
Throw "Error retrieving existing stdout file for service ""$name"""
}
if ($results -ne $stdout)
if ($results -cnotlike $stdout)
{
if (!$stdout)
{
$cmd = "nssm reset ""$name"" AppStdout"
$cmd = "reset ""$name"" AppStdout"
} else {
$cmd = "nssm set ""$name"" AppStdout $stdout"
$cmd = "set ""$name"" AppStdout $stdout"
}
$results = invoke-expression $cmd
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -283,11 +312,12 @@ Function Nssm-Set-Ouput-Files
Throw "Error setting stdout file for service ""$name"""
}
Set-Attr $result "changed_by" "set_stdout"
$result.changed = $true
}
$cmd = "nssm get ""$name"" AppStderr"
$results = invoke-expression $cmd
$cmd = "get ""$name"" AppStderr"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -296,12 +326,12 @@ Function Nssm-Set-Ouput-Files
Throw "Error retrieving existing stderr file for service ""$name"""
}
if ($results -ne $stderr)
if ($results -cnotlike $stderr)
{
if (!$stderr)
{
$cmd = "nssm reset ""$name"" AppStderr"
$results = invoke-expression $cmd
$cmd = "reset ""$name"" AppStderr"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -310,8 +340,8 @@ Function Nssm-Set-Ouput-Files
Throw "Error clearing stderr file setting for service ""$name"""
}
} else {
$cmd = "nssm set ""$name"" AppStderr $stderr"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppStderr $stderr"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -321,6 +351,7 @@ Function Nssm-Set-Ouput-Files
}
}
Set-Attr $result "changed_by" "set_stderr"
$result.changed = $true
}
@ -329,28 +360,28 @@ Function Nssm-Set-Ouput-Files
###
#set files to overwrite
$cmd = "nssm set ""$name"" AppStdoutCreationDisposition 2"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppStdoutCreationDisposition 2"
$results = Nssm-Invoke $cmd
$cmd = "nssm set ""$name"" AppStderrCreationDisposition 2"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppStderrCreationDisposition 2"
$results = Nssm-Invoke $cmd
#enable file rotation
$cmd = "nssm set ""$name"" AppRotateFiles 1"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppRotateFiles 1"
$results = Nssm-Invoke $cmd
#don't rotate until the service restarts
$cmd = "nssm set ""$name"" AppRotateOnline 0"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppRotateOnline 0"
$results = Nssm-Invoke $cmd
#both of the below conditions must be met before rotation will happen
#minimum age before rotating
$cmd = "nssm set ""$name"" AppRotateSeconds 86400"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppRotateSeconds 86400"
$results = Nssm-Invoke $cmd
#minimum size before rotating
$cmd = "nssm set ""$name"" AppRotateBytes 104858"
$results = invoke-expression $cmd
$cmd = "set ""$name"" AppRotateBytes 104858"
$results = Nssm-Invoke $cmd
}
Function Nssm-Update-Credentials
@ -365,8 +396,8 @@ Function Nssm-Update-Credentials
[string]$password
)
$cmd = "nssm get ""$name"" ObjectName"
$results = invoke-expression $cmd
$cmd = "get ""$name"" ObjectName"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -386,8 +417,8 @@ Function Nssm-Update-Credentials
}
If ($results -ne $fullUser) {
$cmd = "nssm set ""$name"" ObjectName $fullUser $password"
$results = invoke-expression $cmd
$cmd = "set ""$name"" ObjectName $fullUser $password"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -396,6 +427,7 @@ Function Nssm-Update-Credentials
Throw "Error updating credentials for service ""$name"""
}
Set-Attr $result "changed_by" "update_credentials"
$result.changed = $true
}
}
@ -412,8 +444,8 @@ Function Nssm-Update-Dependencies
[string]$dependencies
)
$cmd = "nssm get ""$name"" DependOnService"
$results = invoke-expression $cmd
$cmd = "get ""$name"" DependOnService"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -423,8 +455,8 @@ Function Nssm-Update-Dependencies
}
If (($dependencies) -and ($results.Tolower() -ne $dependencies.Tolower())) {
$cmd = "nssm set ""$name"" DependOnService $dependencies"
$results = invoke-expression $cmd
$cmd = "set ""$name"" DependOnService $dependencies"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -433,6 +465,7 @@ Function Nssm-Update-Dependencies
Throw "Error updating dependencies for service ""$name"""
}
Set-Attr $result "changed_by" "update-dependencies"
$result.changed = $true
}
}
@ -447,8 +480,8 @@ Function Nssm-Update-StartMode
[string]$mode
)
$cmd = "nssm get ""$name"" Start"
$results = invoke-expression $cmd
$cmd = "get ""$name"" Start"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -459,9 +492,9 @@ Function Nssm-Update-StartMode
$modes=@{"auto" = "SERVICE_AUTO_START"; "manual" = "SERVICE_DEMAND_START"; "disabled" = "SERVICE_DISABLED"}
$mappedMode = $modes.$mode
if ($mappedMode -ne $results) {
$cmd = "nssm set ""$name"" Start $mappedMode"
$results = invoke-expression $cmd
if ($results -cnotlike $mappedMode) {
$cmd = "set ""$name"" Start $mappedMode"
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -470,6 +503,7 @@ Function Nssm-Update-StartMode
Throw "Error updating start mode for service ""$name"""
}
Set-Attr $result "changed_by" "start_mode"
$result.changed = $true
}
}
@ -482,8 +516,8 @@ Function Nssm-Get-Status
[string]$name
)
$cmd = "nssm status ""$name"""
$results = invoke-expression $cmd
$cmd = "status ""$name"""
$results = Nssm-Invoke $cmd
return ,$results
}
@ -526,9 +560,9 @@ Function Nssm-Start-Service-Command
[string]$name
)
$cmd = "nssm start ""$name"""
$cmd = "start ""$name"""
$results = invoke-expression $cmd
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -537,6 +571,7 @@ Function Nssm-Start-Service-Command
Throw "Error starting service ""$name"""
}
Set-Attr $result "changed_by" "start_service"
$result.changed = $true
}
@ -548,9 +583,9 @@ Function Nssm-Stop-Service-Command
[string]$name
)
$cmd = "nssm stop ""$name"""
$cmd = "stop ""$name"""
$results = invoke-expression $cmd
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -559,6 +594,7 @@ Function Nssm-Stop-Service-Command
Throw "Error stopping service ""$name"""
}
Set-Attr $result "changed_by" "stop_service_command"
$result.changed = $true
}
@ -581,9 +617,9 @@ Function Nssm-Stop
if ($currentStatus -ne "SERVICE_STOPPED")
{
$cmd = "nssm stop ""$name"""
$cmd = "stop ""$name"""
$results = invoke-expression $cmd
$results = Nssm-Invoke $cmd
if ($LastExitCode -ne 0)
{
@ -592,6 +628,7 @@ Function Nssm-Stop
Throw "Error stopping service ""$name"""
}
Set-Attr $result "changed_by" "stop_service"
$result.changed = $true
}
}
@ -612,7 +649,7 @@ Function NssmProcedure
{
Nssm-Install -name $name -application $application
Nssm-Update-AppParameters -name $name -appParameters $appParameters
Nssm-Set-Ouput-Files -name $name -stdout $stdoutFile -stderr $stderrFile
Nssm-Set-Output-Files -name $name -stdout $stdoutFile -stderr $stderrFile
Nssm-Update-Dependencies -name $name -dependencies $dependencies
Nssm-Update-Credentials -name $name -user $user -password $password
Nssm-Update-StartMode -name $name -mode $startMode