Comment puis-je écrire à la norme de l'erreur dans PowerShell?
J'ai du mal à comprendre comment à la fois l'écho du flux d'erreur standard et de rediriger le flux d'erreur d'un exécutable.
Je viens d'un Bourne shell et Korn shell de fond, dont je voudrais utiliser;
# Write to stderr
echo "Error Message!" >&2
# Redirect stderr to file
/do/error 2>/tmp/err.msg
- Parlez-vous de rediriger la sortie d'un exécutable externe, lui-même exécuté à partir de powershell?
Vous devez vous connecter pour publier un commentaire.
Utilisation
Write-Error
à écrire sur la sortie stderr. Pour rediriger stderr à l'utilisation du fichier:ou
Noter que PowerShell écrit les erreurs comme des enregistrements d'erreur. Si vous voulez éviter la sortie détaillée des enregistrements d'erreur, vous pouvez écrire l'erreur info vous-même de la sorte:
-EV
est court (un pseudonyme) pour-ErrorVariable
. Toute erreur sera stockée dans la variable nommée par l'argument de ce paramètre. PowerShell encore signaler l'erreur à la console, à moins que nous rediriger l'erreur de$null
.Write-Error
est de savoir comment vous écrire dans le flux d'erreur.echo
est juste une compatibilité alias pourWrite-Object
qui est de savoir comment votre lieu plein de trucs sur la sortie (stdout) stream.cmd >stdout.log 2>stderr.log
. Compte de la capacité detype
contenu et le tuyau sur la sortie stderr, actuellement, je crois qu'il ne peut pas être fait par les regards des choses.Write-Error "oops" -ev ev 2>&1 > $null
ne redirige pas de quoistderr
.Write-Error "oops"
fonctionne très bien, mais vous êtes coincé avec la sortie détaillée.$ev
variable.stderr
de sortie s'affiche, maisoops
n'est pas en fait redirigé vers stderr à tous (j'ai essayé de l'exécuter en externe etoops
est sorti seulement dans stdout).$null
.$ps = [PowerShell]::Create(); $null = $ps.AddScript('Write-Error Oops 2>&1 > $null'); $ps.Invoke(); $ps.Streams.Error
. Qui affiche il n'y a rien dans le flux d'Erreur. Maintenant essayer de nouveau, mais retirer le2>&1 > $null
partie et vous verrez l'erreur dans le flux d'Erreur.Write-Error "oops" -ev ev 2>&1 > $null
si nous sommes tous d'accord, rien n'est redirigé vers stderr? En outre, l'OP a été clair dans ce qu'il voulait faire, il voulait l'équivalent deecho "Error Message!" >&2
(à savoir les écrire dans le flux d'erreur) en PowerShell.Write-Error
vient de fermer (le seul problème étant que vous ne pouvez pas contrôler le niveau de verbosité), mais lorsque vous rediriger vers $null vous perdre encore que.-ev ev
. Il stocke l'enregistrement d'erreur dans la variable$ev
. De Plus il serait également disponible dans les$error
mondiale. Si nécessaire, vous pouvez accéder au message de l'erreur de texte, plus tard, avec$ev.Exception.Message
. J'ai fait la mise à jour de la réponse à simplifier l'exemple de justeWrite-Error oops -ev ev 2>$null
.Write-Error "oops" -ev ev 2>$null; $ev[0].exception
si le résultat final, dans la mesure du flux aller, est la même queecho oops
.Get-ChildItem C:\Windows -Recurse *.dll -ev ev 2>$null
. Obtenez de l' "rouge", mais vous pouvez accéder à$ev
pour tous les non-terminaison des erreurs générées par la commande.Vous voulez probablement à ceci:
Vous pouvez également voir la suite, mais il suppose que votre PowerShell hôte est une console
fenêtre/de l'appareil, donc je considère qu'il est moins utile:
WriteErrorLine
est une mauvaise idée. Regarder les docs (msdn.microsoft.com/en-us/library/...): Cette méthode écrit une ligne pour l'affichage de messages d'erreur de l'hôte. En d'autres termes, c'est un INTERFACE méthode, qui fonctionne parfois que vous attendez et redirige vers stderr, et parfois (la plupart du temps?) ne pas (voir mklement0 de réponse: stackoverflow.com/a/15669365/67824). Comme Keith Hill dit,Write-Error
est la meilleure option.Remarque:
Cette réponse est d'environ écrit sur la sortie stderr du point de vue de la monde extérieur lorsqu'un script PowerShell est appelé à partir de là; si la réponse est écrite du point de vue de la Windows shell,
cmd.exe
, il s'applique également à Unix coques, telles quebash
lorsqu'il est combiné avec PowerShell de Base.En revanche, de dans Powershell, vous devez utiliser
Write-Error
, comme expliqué dans Keith Hill répondre.Malheureusement, il n'y a pas unifiée approche à partir de deux dans PowerShell et de l'extérieur - voir cette réponse de la mine, pour une discussion.
À ajouter à @Chris Saisir la grande réponse:
Tout
$host.ui.WriteErrorLine
devraient travailler dans tous les hôtes, il n'a pas (par défaut) d'écrire sur la sortie stderr lorsqu'il est invoqué parcmd.exe
, comme à partir d'un fichier de commandes.[Console]::Error.WriteLine
, en revanche, toujours ne.Donc si vous voulez écrire un script PowerShell qui joue bien en termes de flux de sortie lorsqu'il est appelé à partir de
cmd.exe
, utilisez la fonction suivante,Write-StdErr
, qui utilise[Console]::Error.WriteLine
dans l'ordinaire de PS /
cmd.exe
hôte (fenêtre de la console), et$host.ui.WriteErrorLine
autrement:Facultatif des informations de fond:
En interne, PowerShell a plus que la traditionnelle flux de sortie (stdout et stderr), et leur nombre a augmenté au fil du temps (essayez
Write-Warning "I'll go unheard." 3> $null
comme un exemple, et en savoir plus àGet-Help about_Redirection
; notez que la page n'a pas encore compte de flux de6
pourÉcriture d'Information
, introduit dans PowerShell v5).Lors de l'interfaçage avec le monde extérieur, PowerShell doit carte la non-traditionnelle les flux de sortie vers stdout et stderr.
Étrangement, cependant, PowerShell par défaut envoie tous ses flux (y compris
Write-Host
et$host.ui.WriteErrorLine()
de sortie) à stdout lorsqu'il est appelé à partir decmd.exe
, même si la cartographie PowerShell du flux d'erreur vers stderr serait le choix logique. Ce comportement a été en vigueur depuis (au moins) v2 et s'applique toujours comme de la v5.1 (et ne sera probablement pas changer pour des raisons de compatibilité).Vous pouvez le vérifier avec la commande suivante, si vous appelez à partir de
cmd.exe
:La commande écrit à tous les PowerShell flux de sortie (lorsque vous exécutez sur un pré-PowerShell-v5 version, vous verrez un message d'erreur plus concernant
Write-Information
, qui a été introduit dans PowerShell v5) et acmd.exe
rediriger stdout seulement àNUL
(c'est à dire, supprimer stdout;>NUL
).Vous verrez pas de sortie, sauf
cerr
(à partir de[Console]::Error.WriteLine()
, qui écrit directement sur la sortie stderr) - tous PowerShell de cours d'eau ont été envoyés sur la sortie standard stdout.Peut-être encore plus étrangement, il est possible de capturer PowerShell du flux d'erreur, mais seulement avec une redirection:
Si vous modifiez
>NUL
à2>NUL
ci-dessus, il est exclusivement PowerShell est flux d'erreur et$host.ui.WriteErrorLine()
de sortie qui sera supprimée; bien sûr, comme avec n'importe quel de redirection, vous pouvez l'envoyer à un fichier.(Comme il est indiqué,
[Console]::Error.WriteLine()]
toujours sorties vers stderr, si celui-ci est redirigé ou pas.)De donner une information plus ciblée exemple (encore une fois, exécuter à partir du
cmd.exe
):Ci-dessus uniquement sorties
out
-Write-Error
's sortie est supprimée.Pour résumer:
Sans (
cmd.exe
) de redirection ou avec seulement un stdout redirection (>...
ou1>...
), PowerShell envoie tous ses flux de sortie à stdout.Avec un stderr redirection (
2>...
), PowerShell sélectivement envoie ses flux d'erreur à stderr (indépendamment du fait que stdout est également redirigés ou pas).Comme corollaire, la commune suivante idiome ne pas fonctionne comme prévu:
powershell ... >data-output.txt
Ce ne sera pas, comme on pourrait s'y attendre, envoyer uniquement stdout de fichier
data-output.txt
lors de l'impression stderr de sortie à la borne; au lieu de cela, vous auriez à utiliserpowershell ... >data-output.txt 2>err-output.tmp; type err-output.tmp >&2; del err-output.tmp
Il s'ensuit que PowerShell est conscient de
cmd.exe
's les redirections et ajuste son comportement en intentionnellement.(Ceci est également évident à partir de PowerShell production de couleur de sortie dans le
cmd.exe
console tout en se débarrassant les codes de couleur lorsque la sortie est redirigée vers un fichier.)