-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CLI Usage of stdout v. stderr #7289
Comments
I would say, from my perspective, that we should use these two streams as they've been designed, that is:
Another thing we should consider doing, to be good *nix citizens, is to identify |
@blackdwarf I've failed to find a good explanation of STDOUT vs. STDERR @nguerrera brought up an interesting point that STDOUT may benefit from being pipelined to other apps/scripts. STDERR, in this scenario, would get things like diagnostic messages. I think this topic merits some discussion and I'd love to get some community feedback before we write down what we intend. |
@piotrpMSFT http://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout is a pretty nice explanation. TL;DR: STDERR is for diagnostic messages, while STDOUT is for normal app output. Since they are separated, they can be redirected independently, which means that if I redirect STDOUT into a file, STDERR will still show error messages on the console. Actually, this use case was the primary reason the stream was introduced. 🙂 Of course, I'm not saying we should do as I specified, I was just sharing my opinion on the topic. |
Yes I agree. Certain build tools and scripts treat output from each distinctly. For example, if we receive output on Consider if we had a very noisy build on STDOUT, but we still wanted to receive STDERR to a log file. Perhaps we would do something like |
When making the decision for CLI I think we should take a look at our existing tooling and see if it sets up a pattern here. Looking at the tools involved in the CLI toolchain I know for instance the compilers never use StdErr. Even error messages go to stdout. I believe MSBuild is the same but wouldn't swear to it. |
MSBuild does put everything on stdout. But I don't think that's the right design, and I'd rather go with the industry standard (primary output to stdout, warnings and errors to stderr) for any new tool. |
@rainersigwald Every MS tool I can find for dotnet uses stdout for all output. Why have this tool be an outlier in our dotnet pipeline? |
Instead of asking what to log where using broad categories like "warnings" and "primary output" (no idea what that means), shouldn't we start at the consuming end: What text would I actually want to pipe to another command, or what text would get in the way of that? |
My opinion: Differentiating between stdout and stderr only makes sense when all of stdout is expected to be in a well-defined, consumable format, but you also need to report errors that don't match that format. (Think of tools like |
i like the discussions about this - i see the same question in a lot of other (console) projects and i hope that we come to a design decision that can be documented in one of the design repositories! One aspect that comes in mind: In my understanding (not 100% verified) , ConsoleColor can only be used with Console.WriteLine Sample: ConsoleLogger from ASP.Net LoggerFactory (Microsoft.Extensions) is using colorized Output for Trace and Debug Messages. I can imagine, that one reason for non using stderr in the past was the easy usage of colorized (red) outpout on stderr..... my personal long term vision for this:
|
If compilation fails, at least the error code should indicate that, so downstream scripts can make decisions? # in my script
msbuild non-existing.sln
if (!$?) {
echo "this will never hit"
} Comparing it with a popular tool: # powershell
git blah
if (!$?) {
echo "blah is not a command dude!"
}
git status
if (!$?) {
echo "if you are reading this, that means you ran this outside of git repository"
} |
@kasper3 MSBuild sets errorlevel, and I don't repro that:
|
Sharing my experience (which brought me to the repo to search for precisely this issue) My attempt to iterate over migrations so that I could progressively apply-then-rollback failed because the build output is first sent to stdout (
Second scenario: naively intuitive attempt to generate the migration script fails for the same reason (diagnostic build information also goes to stdout).
Both of these scenarios were the first thing I reached to as a long-time *nix/CLI user. That is what is conventional in the ecosystem and is what most (nix/cli) users would reach to intuitively. That these norms are broken makes the tool feel broken or at least unpolished and out of place. It gives one a feeling that the cli is a second-class experience (the first-class experience assumed as "use Visual-Studio-on-Windows"). |
@jasonkarns Can you submit a new issue on dotnet/efcore? I've had similar thoughts recently on making these commands more scriptable. Currently, the best way to consume these commands is to use the |
@bricelam sure can! I had thought about doing that, but assumed that since most of the undesirable output was coming from msbuild, I assumed this would need to be handled by the cli. I'll get an issue written up soon, though, thanks! Adding another "broken" scenario so I don't lose it:
This command executes successfully by returning an exit code of zero; but the command fails to do anything. So the exit status is misleading in a catastrophic way: shell scripts using this command continue as if the command were successful! |
IIRC, we already intercept all that output using ProcessStartInfo.RedirectStandardOutput. We can very easily write it to stderr instead. |
Got hit by this with a simple
So in my case it would at least make sense for build output to go to stderr in the case of dotnet run! |
I do not know what you mean by operational output. Standard output is for the result of the command. That result should be specified and contain no gibberish. In particular, the expected result for |
Just wanted to drop a line to say that this is definitely having an effect on my team and trying to do anything with the CLI during CI/CD pipelines. This issue was first opened with that use case on mind. We need to be able to automate this. My current option is parsing for exact output used to throw errors myself. Even for something like 'dotnet foo', it'd be great to have stderr output. |
@lagomesma are there specific commands that we should focus on the semantics of? I can get on board an interpretation of "dotnet run should map all build related output to stderr" because to do otherwise removes the ability of the app being run to decide on the semantics of stdout. I'm wondering if there are other commands that should do the same, or if run is the source of most folks' pain. |
@baronfel , I'd like to see stderr output on errors on build as well. Ideally, we'd have and work towards consistency across all commands, but I understand if you'd like to start with one and expand to others. |
Thanks for the feedback @lagomesma! I definitely agree that there's a place here for guidance around the proper use of stdout/stderr for tools that ship in or around the SDK (like run, format, etc), as well as recommendations for CLI application authors generally (which I'd include swagger in). I think one major source of trouble for Powershell users especially is that Powershell historically hasn't had a great interaction between the status codes of 'native applications' and Powershell's own error-handling utilities like
With Powershell 7.3 installed and configured the pain point you identified is solved. All of that doesn't change that we could be more consistent, but the dotnet host itself is writing to stderr currently. I was able to redirect the error stream to a file and the output of my terminal was much more manageable:
This is in line with what I'd expect the behavior to be. |
Nice find! So dotnet does provide some type of error code on that output as a "native app" and it's just that Powershell's try catch is not respecting it? |
From what I can tell, yes! And this is something that I'd expect to be the case with all commands that aren't Powershell Cmdlets specifically |
This is an issue that should have been addressed in 2016 at the moment it was decided .NET Core was going to be cross platform. This is a major problem for those of us that use the .NET CLI for build runners that are POSIX compliant. Heck, it’s even a problem against Azure Devops. Here’s a common scenario: Use dotnet pack and publish to publish a nuget package. If that package successfully pushes (does not have a duplicate version) then tag the source tree. You can’t do that easily in Azure devops against “failOnStdErr” because the dotnet cli does not respect stderr. If there is an error we want that to go to stdErr. |
We need to identify how CLI takes advantage of the stdout and stderr streams to set good expectations and help folks consume the CLI effectively, particularly in pipelining scenarios. I'd love to first get the community's thoughts on what stdout and stderr mean to them. Once we come up with guidance we want to follow we can use the issue to track cleaning up the CLI and its scripts.
/cc a bunch of folks who will have opinions
@nguerrera @juergenpf @blackdwarf @glennc @jaredpar @rainersigwald @MattGertz @davidfowl @eerhardt
The text was updated successfully, but these errors were encountered: