HOWTO · PowerShell
Como encerrar um script no Windows PowerShell
Este artigo enumerará várias maneiras de encerrar um script no Windows PowerShell. Serão explicados e definidos todos os comandos, além de exemplos de blocos de script para ilustrar situações de uso.
Interromper um script do PowerShell: escolha a instrução correta
Usar exit Quando um script terminar e precisar retornar um código de saída para quem o chamou. Não use break, continue, ou return Existem duas maneiras intercambiáveis de interromper um script: cada uma controla um escopo diferente. Para interromper um processo separado do sistema operacional, use Stop-Process, não exit.
Essa distinção é importante em tarefas agendadas, trabalhos de CI e scripts chamados por outro processo. Um código de saída claro permite que o chamador decida se a operação foi bem-sucedida. Um código de erro claro permite que o chamador lide com a falha sem continuar silenciosamente.
Finalize um script e defina um código de saída com exit
exit interrompe o script atual ou a instância do PowerShell e define $LASTEXITCODE. Usar 0 para sucesso e um número inteiro diferente de zero documentado para falha. Em um script executado por pwsh -File ou powershell.exe -File, reservar exit para o status final após o script ter tratado os erros esperados.
if (-not (Test-Path -LiteralPath $Path)) {
Write-Error "Missing file: $Path"
exit 2
}
Write-Output 'Processing completed.'
exit 0
A declaração após exit Não executa. No Windows, um código de saída pode ser qualquer inteiro de 32 bits com sinal. Em hosts do tipo Unix, use um código de tamanho de byte positivo para comportamento de shell portátil. Não confie em $LASTEXITCODE Para descrever falhas de cmdlets: é principalmente para códigos de saída de executáveis nativos e o exit declaração.
Deixe apenas a função ou bloco de script atual com return
return Sai do escopo atual, que pode ser uma função, um script ou um bloco de script. Pode escrever um valor opcional no fluxo de saída. Em funções comuns do PowerShell, qualquer saída não capturada também é retornada, portanto, evite usá-la. Write-Output Para mensagens de diagnóstico que não devem se tornar resultados de função.
function Get-ConfigurationValue {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path)) {
return $null
}
return Get-Content -LiteralPath $Path -Raw
}
$value = Get-ConfigurationValue -Path './settings.json'
Usar return Para um resultado antecipado ou cláusula de guarda em uma função. Não use quando um chamador externo precisar de um código de saída do processo; deixe o script de nível superior decidir se deve chamar a função. exit.
Interrompa o processamento com um erro significativo usando throw
throw Cria um erro que encerra o script. Ele desfaz a pilha de chamadas, a menos que… try/catch ou trap Lida com isso. Use-o quando continuar for inseguro e quando quem ligou precisar do motivo da falha.
try {
$content = Get-Content -LiteralPath $Path -ErrorAction Stop
}
catch {
throw "Cannot read '$Path': $($_.Exception.Message)"
}
UM catch O bloco pode registrar o contexto e realizar a limpeza em finallyou relançar o erro original com throwEvite tratar todo código de saída diferente de zero de um programa nativo como uma exceção do PowerShell capturada: comandos nativos definidos $LASTEXITCODE e normalmente não desencadeiam catch Sem configuração explícita de tratamento de erros.
Usar break e continue apenas para blocos de controle
break sai do loop mais próximo ou switch; continue pula para o próximo loop ou switch iteração. Não são comandos gerais de encerramento de script.
foreach ($name in $names) {
if ([string]::IsNullOrWhiteSpace($name)) {
continue
}
if ($name -eq 'stop') {
break
}
Write-Output $name
}
Fora de um laço, switch, ou trapEssas palavras-chave podem procurar um bloco de controle envolvente e encerrar inesperadamente o espaço de execução atual. Evite usá-las em blocos de script de pipeline, como ForEach-Object Para sinalizar o encerramento geral do script.
Interrompa outro processo com Stop-Process
Um script e um processo do sistema operacional são coisas diferentes. Stop-Process Interrompe um processo alvo; não encerra automaticamente o script atual. Selecione o processo com cuidado, especialmente quando um nome puder corresponder a vários processos.
$process = Get-Process -Name notepad -ErrorAction SilentlyContinue
if ($process) {
Stop-Process -InputObject $process
}
Usar -WhatIf Em primeiro lugar, para automação destrutiva, e prefere-se um objeto de processo explícito ou um ID de processo em vez de uma correspondência genérica pelo nome do processo.
Resumo
Usar exit <code> em um limite de script, return para o escopo atual, throw para uma falha terminal, e break ou continue Somente dentro de blocos de controle compatíveis. Use Stop-Process Somente quando a tarefa é encerrar um processo separado. Essa separação torna a automação do PowerShell previsível tanto para as pessoas quanto para as ferramentas que a utilizam.
Retorne o status confiável a um processo de chamada.
Um chamador de automação normalmente observa o código de saída do processo, a saída padrão e o erro padrão. Projete esses canais cuidadosamente. Registre os resultados normais no fluxo de saída de sucesso, os diagnósticos em um fluxo de informações ou de erro apropriado e finalize o script principal com um código documentado.
param([Parameter(Mandatory)][string]$Path)
try {
Get-Content -LiteralPath $Path -ErrorAction Stop |
Measure-Object -Line
exit 0
}
catch [System.Management.Automation.ItemNotFoundException] {
Write-Error "Input file was not found: $Path"
exit 2
}
catch {
Write-Error $_
exit 1
}
O shell que fez a chamada pode inspecionar o status após o PowerShell ser encerrado. De outro processo do PowerShell, esse valor está disponível em $LASTEXITCODESistemas de CI e agendadores também o utilizam para marcar uma etapa como bem-sucedida ou falha. Defina os significados do código na documentação do script, em vez de deixar que os chamadores os infiram a partir das mensagens.
Entender $? e $LASTEXITCODE
$? Informa se o último comando do PowerShell foi executado com sucesso. $LASTEXITCODE Armazena o código de saída do último programa nativo ou um explícito exit de um contexto de script chamado. Eles estão relacionados, mas não são intercambiáveis.
Get-Item -LiteralPath './missing.txt' -ErrorAction SilentlyContinue
Write-Output "Cmdlet succeeded: $?"
git status --porcelain
Write-Output "Native exit code: $LASTEXITCODE"
Um programa nativo pode retornar um status diferente de zero sem gerar o erro de encerramento do PowerShell que catch espera. Inspecione $LASTEXITCODEOu utilize a preferência de erro de comando nativo moderno apropriada quando a versão do PowerShell e a política de script suportadas assim o exigirem. Por outro lado, um erro de cmdlet não atribui necessariamente um novo código de saída nativo significativo.
Chamar outro script sem encerrar o host acidentalmente
O estilo de invocação altera o escopo em que as instruções de controle operam. O operador call executa um script em seu próprio escopo de script. O dot-sourcing executa o script no escopo atual e importa suas funções e variáveis. exit a declaração é mais forte do que return e pode encerrar o processo PowerShell de hospedagem dependendo de como a execução foi iniciada.
# Run in its own script scope.
& './Child.ps1'
# Run in the current scope. Use only when importing definitions is intended.
. './Functions.ps1'
Um script filho reutilizável normalmente deve reportar um objeto ou lançar um erro, permitindo que o script de entrada de nível superior escolha o código de saída final. Isso impede que um auxiliar feche inesperadamente um shell interativo, um executor de testes ou um host de automação principal.
Usar return Cuidado em Pipelines e Funções
O PowerShell grava toda a saída de sucesso não capturada de uma função em seu fluxo de resultados, não apenas a expressão que a segue. returnPortanto, as strings de diagnóstico podem alterar o valor de retorno aparente.
function Get-Port {
Write-Verbose 'Reading configured port'
return 8080
}
$port = Get-Port -Verbose
Write-Verbose usa o fluxo detalhado, então $port permanece o número inteiro pretendido. Uma expressão de string simples ou Write-Output antes return também passaria a fazer parte de $port. Usar return Principalmente para sair do escopo atual antecipadamente; gerenciar fluxos de forma deliberada ao retornar dados.
Limpeza de preservação com finally
Quando um script abre um recurso, use finally Para limpeza que deve ser executada independentemente de a operação ser bem-sucedida ou lançar uma exceção. Isso é mais seguro do que colocar a limpeza somente após um código que pode terminar prematuramente.
$stream = $null
try {
$stream = [System.IO.File]::OpenRead($Path)
# Process the stream.
}
catch {
throw
}
finally {
if ($null -ne $stream) {
$stream.Dispose()
}
}
Evite ligar exit bem no fundo do try Bloqueie apenas para expressar falha. Lance uma exceção ou retorne ao ponto de entrada para que a política de limpeza e status do script permaneça visível e testável.
Gerencie o cancelamento separadamente da falha.
Um usuário pressionando Ctrl+C, uma tarefa sendo interrompida e um script detectando uma entrada inválida são eventos diferentes. Não force todas as situações a terem o mesmo código de saída. Para automação não interativa, documente quais códigos significam falha na validação, recursos indisponíveis ou falha em um comando externo. Para ferramentas interativas, forneça contexto suficiente para que o usuário decida o que fazer em seguida.
Stop-Process -Force Não é um mecanismo de cancelamento geral. Ele pode impedir que o aplicativo alvo limpe arquivos ou estado, e a interrupção de processos protegidos pode exigir permissões elevadas. Prefira o mecanismo de desligamento normal do aplicativo alvo, quando houver. Use o encerramento forçado de processos somente quando essa consequência for compreendida.
Escolha a declaração do limite pretendido
Pergunte qual limite deve parar. Para interromper uma iteração do loop, use continuePara sair de um loop ou switch, usar breakPara sair da função, script ou bloco de script atual, use returnPara relatar uma falha que os chamadores possam detectar, use throwPara finalizar o script de nível superior ou o host do PowerShell com um status, use exitPara encerrar um processo diferente do sistema operacional, use Stop-Process.
Manter esses limites separados melhora os testes. Uma função que retorna um valor ou lança uma exceção pode ser invocada por um teste unitário sem encerrar o processo de teste. Um script de entrada simples pode traduzir seu resultado em um código de saída estável para o shell, o agendador ou o sistema de implantação.
Conta para o host do PowerShell
O efeito visível de exit Depende de como o PowerShell está hospedado. Em um console interativo, ele pode fechar a sessão atual do PowerShell. Em um script executado como um processo filho, ele encerra esse processo filho e retorna o controle para o processo pai. Em um ambiente de execução ou editor incorporado, o comportamento do host pode ser diferente, o que é mais um motivo pelo qual funções reutilizáveis devem retornar ou lançar uma exceção em vez de chamar uma exceção. exit eles mesmos.
Ao invocar o PowerShell a partir de cmd.exeSeja em Bash, Python ou um executor de compilação, teste a linha de comando real usada em produção. Citando, -Command contra -FilePerfis e scripts de encapsulamento podem afetar qual processo detém o status final. Capture a saída e o código de saída separadamente durante os testes para que uma mensagem correta não oculte um status incorreto.
Preservar o fracasso de um programa externo
Um script de encapsulamento às vezes precisa retornar o status exato de uma ferramenta nativa. Armazenar $LASTEXITCODE imediatamente, pois a execução de outro comando nativo pode substituí-lo.
git fetch --all
$gitExitCode = $LASTEXITCODE
if ($gitExitCode -ne 0) {
Write-Error "git fetch failed with exit code $gitExitCode"
exit $gitExitCode
}
Se a ferramenta nativa puder retornar códigos fora do intervalo de compatibilidade, mapeie-os para um código de script documentado. Inclua o código original no registro de erros ou na saída de diagnóstico. Isso fornece aos usuários um contato estável sem descartar as informações necessárias para a solução de problemas.
Recomendação final
Mantenha a lógica de negócios em funções que retornam dados ou lançam erros, e mantenha a política de encerramento do processo em um pequeno script de nível superior. Essa estrutura é mais fácil de testar, reutilizar e hospedar. Use palavras-chave de controle de loop somente onde sua estrutura de controle for visível e reserve o encerramento forçado do processo para casos em que o desligamento correto não estiver disponível.