How to get exit status of a shell command used in

2019-04-03 06:59发布

问题:

I have a makefile rule in while I am executing a linux tool. I need to check the exit status of the tool command, and if that command fails the make has to be aborted.

I tried checking with $?, $$? \$? etc in the makefile. But they gives me syntax error when makefile runs.

What is the right way to do this ?

Here is the relevant rule in Makefile

    mycommand \
    if [ $$? -ne 0 ] \
    then \
        echo "mycommand failed" \
        false \
    fi

回答1:

In the makefile-:

mycommand || (echo "mycommand failed $$?"; exit 1)

Each line in the makefile action invokes a new shell - the error must be checked in the action line where the command failed.

If mycommand fails the logic branches to the echo statement then exits.



回答2:

Here are a couple of other approaches:


shell & .SHELLSTATUS

some_recipe:
    @echo $(shell echo 'doing stuff'; exit 123)
    @echo 'command exited with $(.SHELLSTATUS)'
    @exit $(.SHELLSTATUS)

Output:

$ make some_recipe

doing stuff
command exited with 123      
make: *** [Makefile:4: some_recipe] Error 123

It does have the caveat that the shell command output isn't streamed, so you just end up with a dump to stdout when it finishes.


$?

some_recipe:
    @echo 'doing stuff'; exit 123;\
    EXIT_CODE=$$?;\
    echo "command exited with $$EXIT_CODE";\
    exit $$EXIT_CODE

Output:

$ make some_recipe

doing stuff                  
command exited with 123      
make: *** [Makefile:2: some_recipe] Error 123

It's essentially one string of shell commands, separated by semi-colons. Escaping any new lines you want is annoying and it's easy to forget the semi-colons, but I went with this approach purely because of the caveat mentioned above.



回答3:

If all you want is for the make to be aborted iff the tool exits with a nonzero status, make will already do that by default.

Example Makefile:

a: b
    @echo making $@
b:
    @echo making $@
    @false
    @echo already failed

. This is what happens with my make:

$ make
making b
make: *** [Makefile:6: b] Error 1

Make sure partially or wholly created targets are removed in case you fail. For instance, this

a: b
    @gena $+ > $@
b:
    @genb > $@

is incorrect: if on the first try, genb fails, it will probably leave an incorrect b, which, on the second try, make will assume is correct. So you need to do something like

a: b
    @gena $+ > $@ || { rm $@; exit 1; }
b:
    @genb > $@