I have to do this:
scala -version 2>&1 | sed 's/.*version \([0-9]*\.[0-9]*\).*/\1/'
Instead of this:
scala -version | sed 's/.*version \([0-9]*\.[0-9]*\).*/\1/'
so I am wondering why does scala -version
(sometimes maybe ...) put its result on stderr
?
CodePudding user response:
Actually, in Unix stderr is not used for errors only.
It's more like stdin and stdout are using for the default piping streams (cmd1 | cmd2 | cmd3
) and sdterr is everything that the command creators thought that should not go into this default pipeline, and instead should be shown to the user who build it. It includes errors, but sometimes also information about progress, configuration, diagnostics, etc.
Let's see some example of that:
echo "2 2 * 2" | scala | grep "res"
This would treat scala as something that takes source as input and prints the results of evaluation on output. But it still prints some stuff on stderr, and when you run it you'll see
Type in expressions for evaluation. Or try :help.
Jul 08, 2022 9:32:44 AM org.jline.utils.Log logr
WARNING: Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
scala> val res0: Int = 6
On a first glance it is redundant but when you look closely it tells some interesting things like WARNING: Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
which is nice to see as you are debugging your script, and not go into the stream where you are only expecting to see the results of the execution.
What would happen if you added -version
after scala
?
> echo "2 2 * 2" | scala -version | grep "res"
Scala code runner version 2.13.8 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.
Script still runs - it's shell so you can glue a lot of things together whether it makes sense or not, so it's expected. But this script doesn't do anything reasonable - there is no code processing output from scala -version
and if version landed on stdin you'd see empty result, not knowing what happened. But since it landed on stderr you see what happened, and can fix the script.
And if you actually wanted to process scala -version
output, it's just one 2>&1
away as you noticed.
There are also other things to consider like mentioned in comments: consistency with what java -version
does, no promise to print such information to stdin. Also, it might have been made this way to be internally consistent: scala
might use stdin for code input and stdout for code execution exclusively, and anything else is wired to some global logger printing on stderr. Finally, while there are some conventions what should and should not go into stderr, none of that is set in stone, so you should not come with predefined expectations. Authors will do what they find the most pragmatic.