5

I am using pylint utility that returns this error codes:

Pylint should leave with following status code:

* 0 if everything went fine
* 1 if a fatal message was issued
* 2 if an error message was issued
* 4 if a warning message was issued
* 8 if a refactor message was issued
* 16 if a convention message was issued
* 32 on usage error

status 1 to 16 will be bit-ORed so you can know which different
categories has been issued by analysing pylint output status code

Now I need to determine if fatal or error message occured in Bash. How to do that? I guess I need bit operations for that ;-)

Edit: I know I need to do bitwise and with number three (3) and test against null to see if fatal message or error message were issued. My problem is simple: bash syntax to do it. Input is $?, ouptut is again $? (e.g. using test program). Thanks!

lzap
  • 16,417
  • 12
  • 71
  • 108

7 Answers7

5

in Bash you can use double parenthesis:

#fatal error
errorcode=7
(( res = errorcode & 3 ))
[[ $res != 0 ]] && echo "Fatal Error"
neurino
  • 11,500
  • 2
  • 40
  • 63
  • 2
    Thanks. I already found it and its shorter but thanks :-) [ $(($NUMBER & 3)) -ne 0 ] && echo Fatal error or error was issued – lzap Jul 08 '11 at 15:50
  • 4
    A useful variation is `( pylint $THE_PYLINT_COMMAND_ARGUMENTS; exit $(($? & 35)) )`, which zeroes out all the less-than-an-error exit codes in a way that integrates nicely into a broader script. – Donal Fellows Mar 14 '18 at 13:43
  • @DonalFellows: Thanks! This should be the actual answer – Günther Jena Sep 13 '18 at 07:33
2

To embed something like this in a script with errexit set, you could use a form like the following:

#!/bin/bash
set -o errexit
set -o nounset
(
    rc=0;
    pylint args args || rc=$?;
    exit $(( $rc & 35 )) # fatal=1 | error=2 | usage error=32
)

Inspired from David's comment and this answer

You could poke at it by replacing the pylint blah blah with python -c "exit(4+8+16)"

Nick T
  • 25,754
  • 12
  • 83
  • 121
2

Bash supports bitwise operators...

$ let "x = 5>>1"
$ echo $x
2
$ let "x = 5 & 4"
$ echo $x
4
Andrew White
  • 52,720
  • 19
  • 113
  • 137
  • 1
    How to write it on the one line to test if flags "1" and "2" are set? Something like [ $? & 2 ] && echo Error. It does not work for me :-( – lzap Jul 08 '11 at 15:08
2

A fatal message will be issued iff the status is odd, iff it has a 1 in the least significant digit.

An error message will be issued iff the status has a 1 in the next most significant digit.

So you want to check whether the last two digits are both 1; in other words, to check whether the bitwise and of your status code with 0b11 is three.

Katriel
  • 120,462
  • 19
  • 136
  • 170
  • @lzap: oops, sorry. In that case you should check whether the final _two_ bits are both one; in other words, take the bitwise and with 0b11 == 3. – Katriel Jul 08 '11 at 15:09
  • Yeah, I know what to do. What I dont know is the bash syntax for it :-) Lemme edit my question. – lzap Jul 08 '11 at 15:13
2

Got it!

[ $(($NUMBER & 3)) -ne 0 ] && echo Fatal error or error was issued

Thanks!

lzap
  • 16,417
  • 12
  • 71
  • 108
1

The return code of the last executed command in bash is available as $?.

[/tmp] % touch bar
[/tmp] % ls /tmp/bar 
/tmp/bar
[/tmp] % echo $?
0
[/tmp] % ls /tmp/baaz
ls: /tmp/baaz: No such file or directory
[/tmp] % echo $?
1
[/tmp] % 

If you were to call an external command from say python's subprocess module, you could get the return code of the external command from the Popen object once the subprocess has exited.

Matt Anderson
  • 19,311
  • 11
  • 41
  • 57
1

Using (probably sub-optimally) the bash arithmetic stuff:

for status in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
do
    if [ $status = 0 ]
    then echo $status: it worked perfectly
    elsif [ $(( $status & 3 )) != 0 ]
    then echo $status: a fatal or error message was sent
    else echo $status: it sort of worked mostly
    fi
done

Output:

0: it worked perfectly
1: a fatal or error message was sent
2: a fatal or error message was sent
3: a fatal or error message was sent
4: it sort of worked mostly
5: a fatal or error message was sent
6: a fatal or error message was sent
7: a fatal or error message was sent
8: it sort of worked mostly
9: a fatal or error message was sent
10: a fatal or error message was sent
11: a fatal or error message was sent
12: it sort of worked mostly
13: a fatal or error message was sent
14: a fatal or error message was sent
15: a fatal or error message was sent
16: it sort of worked mostly

I strongly suspect that the scripting (testing) can be made tighter or cleaner (specifically in the elif clause), but this seems to work (and I need to get to work).

pylint ...
status=$?     # Catch exit status before it changes
if [ $status = 0 ]
then echo $status: it worked perfectly
elsif [ $(( $status & 3 )) != 0 ]
then echo $status: a fatal or error message was sent
else echo $status: it sort of worked mostly
fi
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278