#1134 Issue closed: RFC: Use proper exit codes (backward incompatible change)

Labels: enhancement, bug, cleanup, discuss / RFC, won't fix / can't fix / obsolete

jsmeix opened issue at 2016-12-20 11:46:

For a future ReaR version this is a request for comments
whether I should change ReaR to use proper exit codes.

In particular this would mean to change the existing misuse
of the general error exit code 1 to signal something to the user
by a more appropriate exit code value.

According to the Advanced Bash-Scripting Guide
http://www.tldp.org/LDP/abs/html/exitcodes.html
those are the already used bash exit codes:

1     Catchall for general errors
e.g.  let "var1 = 1/0"
      Miscellaneous errors,
      such as "divide by zero" and
      other impermissible operations

2     Misuse of shell builtins
e.g.  empty_function() {}       
      Missing keyword or command,
      or permission problem

126   Command invoked cannot execute
e.g.  /dev/null 
      Permission problem or
      command is not an executable

127   "command not found"
e.g.  illegal_command   
      Possible problem with $PATH or a typo

128   Invalid argument to exit
e.g.  exit 3.14159      
      exit takes only integer args
      in the range 0 - 255

128+n Fatal error signal "n"
e.g.  kill -9 $PPID of script   
      $? returns 137 (128 + 9)

130   Script terminated by Control-C
e.g.  Ctl-C     
      Control-C is fatal error signal 2, 
      (130 = 128 + 2, see above)

255*  Exit status out of range
e.g.  exit -1
      exit takes only integer args
      in the range 0 - 255

The author of the Advanced Bash-Scripting Guide
proposed restricting user-defined exit codes to the
range 64 - 113 (in addition to 0, for success),
to conform with the C/C++ standard but
an update of /usr/include/sysexits.h allocates
previously unused exit codes from 64 - 78.

Accordingly exit codes used by ReaR should currently
be in the range 79 - 113 (in addition to 0, for success).

To be safer against more addons in sysexits.h
I suggest exit codes used by ReaR should be in the
range 100 - 109 (in addition to 0, for success).

Ten ReaR-specific exit codes 100, 101, ... 109 should be
sufficiently future-proof because currently only one
ReaR-specific exit code "EXIT_CODE=1" is used
in current ReaR GitHub master code:

$ find * | xargs grep 'EXIT_CODE'
usr/share/rear/layout/compare/default/500_compare_layout.sh:    EXIT_CODE=1
usr/share/rear/layout/compare/default/510_compare_files.sh:        EXIT_CODE=1
usr/share/rear/layout/save/NSR/default/650_check_iso_recoverable.sh:   EXIT_CODE=1

jsmeix commented at 2017-01-23 11:41:

See also
https://github.com/rear/rear/pull/1171#issuecomment-274449562
and subsequent comments.

jsmeix commented at 2017-01-24 14:37:

In contrast to what @schlomo prefers according to
https://github.com/rear/rear/issues/564#issuecomment-83552182
that only zero exit code means success
and all other exit codes mean error,
meanwhile I think it is in practice not possible
to distinguish in all cases between success and error, cf.
https://github.com/rear/rear/pull/1171#issuecomment-274449562

the warning is justified
as it really means "I don't know"

Meanwhile I think it is in practice needed to have some
special non-zero exit codes that signal something to the user.

While implementing
https://github.com/rear/rear/pull/1176
I found good examples in traditional Unix tools
where it is also not possible to distinguish
cases between success and error:

# man cmp
...
cmp - compare two files byte by byte
...
Exit status is 0 if inputs are the same,
1 if different, 2 if trouble.
...

# man diff
...
diff - compare files line by line
...
Exit status is 0 if inputs are the same,
1 if different, 2 if trouble.
...

Furthermore I think it does not help the user how to deal
with the actual result of a 'rear' run when such special
non-zero exit codes do not exists because then the user
would have to implement additional special tests that
somehow read the actual state out of wherever that
state was stored.

I think when some special non-zero exit codes exist
that signal something to the user it makes it easier for
the user to test the actual result because he only needs
to test the exit code value (and nothing else) like

rear mkbackup
exit_code=$?
case $exit_code in
    (0)
        echo success
        ;;
    (10[0-9])
        echo ReaR signal $exit_code between 100 and 109
        ;;
    (*)
        echo error exit code $exit_code
        ;;
esac

[Export of Github issue for rear/rear.]