question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Suggestion: Add redirection syntax that allows in-memory collection of stderr lines output by external utilities, akin to the -ErrorVariable common parameter

See original GitHub issue

This was first proposed as part of a lengthy exchange in #3996, but I thought it deserved its own post.

tl;dr

In order to collected stderr output (separately) from an external-utility call in memory, I suggest supporting the following new redirection syntax that allows capturing stderr lines in a variable, akin to the common -ErrorVariable parameter for cmdlets (the sample cmd command is designed to produce both stdout and stderr output):

# Wishful thinking: Collect stderr lines in given variable $stderrOutput via 2>&
$stdoutOutput = cmd /c ver '&' dir \nosuch 2>&stderrOutput 

Instead of what you must currently do:

$stderrFile = New-TemporaryFile
$stdoutOutput = cmd /c ver '&' dir \nosuch 2>$stderrFile
$stderrOutput = Get-Content $stdErrFile
Remove-Item $stderrFile

The current behavior is to pass stderr output generated by external utility calls (e.g., to git) through to the console - stderr output is not recorded in $Error, which makes sense, given that many utilities write much more than just error information to stderr, and that the presence of stderr input doesn’t imply actual errors.

Sometimes it is necessary to inspect stderr output, however, which is currently not easily accomplished:

You can redirect stderr output by redirecting PowerShell’s error stream: 2>..., but you’re faced with 2 options, neither of which is convenient:

  • Either: redirect stderr output to a file with 2>filename

  • Or: redirect stderr output into the success stream with 2>&1 to produce a combined stream from which you can later filter out the stderr lines by type ([System.Management.Automation.ErrorRecord]).

Therefore, I propose a new redirection syntax that allows capturing stderr lines in a variable, akin to the common -ErrorVariable parameter for cmdlets, so that:

  • foo.exe 2>&errs would be the external-utility-call equivalent of a (fictitious) Invoke-Foo -ErrorVariable errs 2>$null call, with errors getting collected in variable $errs in both cases.

  • Additionally, to allow stderr output to also be passed through while being collected:
    foo.exe 2>&|errs could be the equivalent of Invoke-Foo -ErrorVariable errs

The suggestion is to use >&varName syntax, because & is already established as having into-a-different-target(-stream) semantics, yet currently only a digit is supported after the & (the index of a different PS stream).
(There is still ambiguity, given that $1 is a valid variable name, but I think that wouldn’t be a real-world concern.)

Also, given that -ErrorVariable supports a + prefix to the variable name to indicate that the existing variable value should be appended to, this new syntax should support that too.

Environment data

PowerShell Core v6.0.0-beta.4

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:11
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

10reactions
JamesWTruhercommented, Jun 12, 2020

Rather than this approach which relies on syntactic element, it was possible to create redirection as follows:

PS> write-error bad 2>variable:var1

and

$a = 1..5
6..9 | write-error 2>>variable:a

while not as terse as a sigil, it required very little change. It also works with native executables ala:

PS> $result = /bin/ls -ld . sdfljksdj 2>variable:whoops
PS> $result
drwxr-xr-x  93 james  staff  2976 Jun 12 12:05 .
PS> $whoops
ls: sdfljksdj: No such file or directory

a further by-product is that now all streams may be redirected to a variable

$a = . { 
>> write-error bad
>> write-warning warning
>> write-verbose -verbose 'and here'
>> write-debug -debug 'yep, debug too'
>> write-information 'and info'
>> } 2>variable:e 3>variable:w 4>variable:v 5>variable:d 6>variable:i
PS> $e
Write-Error: bad
PS> $w
WARNING: warning
PS> $v
VERBOSE: and here
PS> $d
DEBUG: yep, debug too
PS> $i
and info

and append works too

PS> 1..3 | write-error 2>variable:e         
PS> /bin/ls -ld / lsjdflkjsdlj 2>>variable:e
drwxr-xr-x  23 root  admin  736 Jun  8 14:35 /
PS> $e
Write-Error: 1
Write-Error: 2
Write-Error: 3
ls: lsjdflkjsdlj: No such file or directory

I think that using variable:<name> is ok - I think it’s somewhat natural for the PowerShell environment. It required a relatively simple change to the engine and a small extension to set-variable. I can submit a PR if you think this is reasonable.

6reactions
Jaykulcommented, Jun 12, 2020

I would happily vote yes to making each and every one of the numbered streams generically redirectable to any content provider PSDrive path. That makes sense, it’s always frustrating when something looks like it builds on the content providers and doesn’t.

I think a version of Tee-Object that could capture streams beyond should be technically impossible, because only output goes to cmdlets in a pipeline, and it would be super confusing if there was some magic thing that looked like a cmdlet but could somehow intercept other output before it gets to the host.

As a use case / example: we love @dlwyatt’s PowerShellLogging module, but what it does is a dirty hack that shims the host. Unless you’re going to make interfaces public so that sort of host interception logging would be possible in every host without using private methods, I don’t need a cmdlet version of redirection, and I don’t want weird new syntax for capturing without redirecting (that is, passthrough capturing)

P.S. Alias: is a content drive and works just as well as ENV: for holding strings… 🤯

Read more comments on GitHub >

github_iconTop Results From Across the Web

about Redirection - PowerShell
Explains how to redirect output from PowerShell to text files.
Read more >
Powershell redirect std error to variable
The idea is simple: save the "red" (std error) text in Powershell console in a variable. The command I receive is an arbitrary...
Read more >
Input Output Redirection in Linux
Merge Redirection: This allows you to redirect the output of a command or a program to a specific file descriptor instead of standard...
Read more >
Input Output Redirection in Linux/Unix Examples
Redirection is a feature in Linux such that when executing a command, you can change the standard input/output devices.
Read more >
Untitled
Set oOutput = oExc.StdOut. Parsing Command-Line Output with PowerShell -- Microsoft … Suggestion: Add redirection syntax that allows in-memory .
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found