opam
opam copied to clipboard
In verbose mode, errors are sent to stdout
When executing an install command in --verbose mode, any messages that are printed to /dev/stderr by a build command are redirected to /dev/stdout by Opam. It would be better if they would still end up in /dev/stderror, because this allows for easy separation of errors and normal messages.
You can use for that the environment variable OPAMMERGEOUT
Ah, I didn't know about that one. Thanks. However, I just tried to run
export OPAMMERGEOUT=0 && opam install . --verbose 1> /dev/null
on my project, and it does not display any errors, even though I know that running the exact same build command that Opam uses does produce warnings on stderr. So either I'm using it wrong, or there is a bug somewhere.
It unmerges outputs for command outputs files. By default, stderr & stdout are merged in .out file.
Those files are in .opam/log (unless you select another one with OPAMLOGS). They are displayed in the error report when an error occurs.
In a successful run, file names are not logged at all (we should at least add it at a 2+ debugging level). For the moment you can clean your log dir (or create a temp new one) and look at those files: pkg-xxx-.info file gives the command ran, and pkg-xxx.{err,out} corresponding outputs (if unmerged).
On direct opam output, stderr is used for debug logs and error reports.
Note that even during a successful run, warnings can still be printed to stderr by the build command. Given that OPAMMERGEOUT can separate pkg-xxx.err and pkg-xxx.out, it would make sense to me that --verbose mode would also send these logs to the proper terminal outputs. Or am I still misunderstanding?
It makes sense yes, but it's not so trivial (display x.err in stderr) to implement as it need to give the context. As some actions are done in parallel, user can't know from which action originates the warning. One solution could be, when outputs are unmerged, to display a warning report, like the errors one.
@AltGr what's the original reason for the merged outputs?
From experience, although it's counter-intuitive, you generally lose more information by separating stderr and stdout ; the reason being that relative ordering generally matters, and is in many cases a more relevant information than wether each line was printed to stdout or stderr. For example, a compiler may print the context to stdout, then an error to stderr.
I believe --verbose will only work for stdout, if you disable output merging, which might be your issue.
I don't know what your use-case is, but you might be interested in the --json output which includes the build logs.
From experience, although it's counter-intuitive, you generally lose more information by separating stderr and stdout
Yes, this is indeed true. However, in this case, a large amount of information was printed on stdout, and I wanted to know if there were warnings printed to stderr at all. Then it is useful just to check if something gets printed to stderr at all. However, I guess I can also look at pkg-xxx.err instead. So this is not a super critical problem, just unexpected.
I don't know what your use-case is, but you might be interested in the --json output which includes the build logs.
That is indeed an interesting option. However, on opam 2.0.7, when I run opam install xxx -v --json=test.json, the resulting json does not contain a build log, nor a link to a file containing a log:
{"opam-version":"2.0.7","command-line":["opam","reinstall",".","--json=test.json","--verbose"],"command-line":["opam","reinstall",".","--json=test.json","--verbose"],"switch":"/home/lasse/Documents/Projects/Tactician/develop","request":{"action":"reinstall","install":["coq-tactician.8.11.dev"],"remove":[],"upgrade":[],"criteria":"-changed,-count[version-lag:,false]"},"solution":[{"remove":{"name":"coq-tactician","version":"8.11.dev"}},{"install":{"name":"coq-tactician","version":"8.11.dev"}}],"results":[{"action":{"build":{"name":"coq-tactician","version":"8.11.dev"}},"result":"OK","duration":4.4425950050354},{"action":{"remove":{"name":"coq-tactician","version":"8.11.dev"}},"result":"OK","duration":0.0446019172668457},{"action":{"install":{"name":"coq-tactician","version":"8.11.dev"}},"result":"OK","duration":5.933771848678589}]}
Mhm, but now that I'm trying this again, it seems that there are also problems with he logs:
- Opam only keeps logs in
.opam/log/when a build fails, even if set setOPAMKEEPLOGS. - Opam does not respect
OPAMLOGS. Log files always end op in.opam/logs/, even if I set something likeexport OPAMLOGS=$(pwd).
This was discussed this morning. Steps:
- [ ] https://github.com/ocaml/opam/issues/4490#issuecomment-762339185 needs to be triaged/reproduced/fixed
- [ ] We need to verify that
OPAMMERGEOUT=0is behaving correctly w.r.t. the logs written in~/.opam - [ ] Propose for opam 2.2 that
OPAMMERGEOUT=0 opam --verboseshould write always write the stderr logs to stderr (once that's been double-checked that it's not already the case!)