24

I have a script that I am using to automatically sync various remote git repositories. One thing I am trying to do with my scripts is to capture the output of stderr from every command and write all those errors into a text file that is then emailed to me after the script has finished. This will alert me to any problems that I need to fix.

However, I'm having a problem with the following two lines:

{
    git fetch --prune-tags github-fetch master
    git push github master 
} 2> '/tmp/stderr-contents-sync_git_repositories.txt'

The problem is that the git fetch line is writing the following to stderr:

From https://github.com/XJDHDR/xjdhdr-random-code.wiki
 * branch            master     -> FETCH_HEAD
   13af304..333d602  master     -> github/master

And the git pull line is writing this:

To ssh://github.com/XJDHDR/xjdhdr-random-code.wiki.git
   333d602..da65970  master -> master

My problem is that neither of these are errors and they are emailed every time I run the script. I would like to know if it is possible to either stop git from writing these non-errors to stderr or filter these sort of messages out of the stderr output while preserving genuine errors.

KyleMit
  • 30,350
  • 66
  • 462
  • 664
XJDHDR
  • 494
  • 5
  • 15
  • 2
    Maybe you're looking for the `-q`/`--quiet` option? I'm not sure if it hides output like this. – wjandrea Jul 13 '19 at 04:35
  • The `--quiet` option does hide the output I mentioned. I am concerned whether that option would also hide any errors that occur as well? Or are errors still sent? – XJDHDR Jul 13 '19 at 04:41
  • @XJDHDR See my answer: Git does not use stderr only for errors but also for informative message. The approach I propose should allow you to capture failed command execution (with their stdout/stderr) instead of relying solely on stderr anlone. – VonC Jul 13 '19 at 05:17
  • The docs for fetch and push say the `-q` option @wjandrea mentioned does shut off all output except actual errors on each -- in particular, it shuts off the progress reports to stderr. – jthill Jul 14 '19 at 06:30
  • **See Also**: [Git clone: Redirect stderr to stdout but keep errors being written to stderr](https://stackoverflow.com/q/34820975/1366033) – KyleMit Jan 02 '22 at 23:08

1 Answers1

8

write all those errors into a text file

Those are not always error, considering most Git commands outputs information message on stderr, as I mentioned here:

stderr as it is just informative messages, not to be consumed by machines.

If it better to test the exit status of the command and email both stdout and stderr if said exit status differs from 0

Plus, you are doing two redirections: > followed by >: the second one would recreate /tmp/stderr-contents-sync_git_repositories.txt: that second redirection should be >>, not >.

So:

git fetch --prune-tags github-fetch master > tmp 2>&1 || cat tmp > '/tmp/stderr-contents-sync_git_repositories.txt'
git push github master > tmp 2>&1 || cat tmp >> '/tmp/stderr-contents-sync_git_repositories.txt'

Here I override a tmp file on each command (with their stdout/stderr), and if that command fails, I write to, or I append to /tmp/stderr-contents-sync_git_repositories.txt.

This is easier than your edit, where you redirect both commands to a file, even if one of them might have failed.

That is why I do cmd1 || cat >> file: the >> part only runs if cmd1 fails.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • My edit was to more closely reflect what my actual script looks like. The actual script has around 35 lines of code inside those braces and I need to capture the stderr output for all of them. It is less tedious to simply enclose all of them inside braces and have one redirect than to add a redirect for every command. This is what ShellCheck recommends as well: https://stackoverflow.com/a/30194723/6627890 – XJDHDR Jul 13 '19 at 05:45
  • @XJDHDR less tedious, but less precise: you need to test the exit status of each command as I explained the answer: stderr is not a reliable indicator of issues here. – VonC Jul 13 '19 at 05:46
  • I'll cross that bridge when I reach it. Otherwise, thanks for the answer. – XJDHDR Jul 13 '19 at 06:36
  • 1
    Just a note to do this with each git command (as in the answer), instead of at the end of the curly braces shown in the question. If one command in the braces fails, the output from the braces could still be success. – ki9 Jan 13 '21 at 19:15