Is there a way to print message using makefile whenever any makefile command fails? - makefile

I was compiling a program using makefile and wanted to display a message to the user if there is any error in the program.
I searched for this and found that the exit status is zero if make is successful else it is non-zero.
How to use these values of exit status to accomplish the above task or is there any other way of doing so ?

You have to create a bash script and call make command in that, you can check result of each command(or which command you want to check if successful) and print a message using echo if it fails as
#!/bin/bash
cd <YOUR_DIRECTORY_CONTAINING_MAKEFILE>
make
if [ $? -ne "0" ]; then
echo "Make failed"
exit 1
fi
echo "make Successful"
$? holds result of last command.
Now, to make your program and see result, you have to run this bash script

Related

bash run multiple files exit condition

I have a function like so
function generic_build_a_module(){
move_to_the_right_directory
echo 'copying the common packages'; ./build/build_sdist.sh;
echo 'installing the api common package'; ./build/cache_deps.sh;
}
I want to exit the function if ./build/build_sdist.sh doesn't finishes successfully.
here is the content ./build/build_sdist.sh
... multiple operations....
echo "installing all pip dependencies from $REQUIREMENTS_FILE_PATH and placing their tar.gz into $PACKAGES_DIR"
pip install --no-use-wheel -d $PACKAGES_DIR -f $PACKAGES_DIR -r $REQUIREMENTS_FILE_PATH $PACKAGES_DIR/*
In other words, how does the main function generic_build_a_module "knows" if the ./build/build_sdist.sh finished successfully?
You can check the exit status of a command by surrounding it with an if. ! inverts the exit status. Use return 1 to exit your function with exit status 1.
generic_build_a_module() {
move_to_the_right_directory
echo 'copying the common packages'
if ! ./build/build_sdist.sh; then
echo "Aborted due to error while executing build."
return 1
fi
echo 'installing the api common package'
./build/cache_deps.sh;
}
If you don't want to print an error message, the same program can be written shorter using ||.
generic_build_a_module() {
move_to_the_right_directory
echo 'copying the common packages'
./build/build_sdist.sh || return 1
echo 'installing the api common package'
./build/cache_deps.sh;
}
Alternatively, you could use set -e. This will exit your script immediately when some command exits with a non-zero status.
You have to do the following:-
Run both the script in background and store their respective process id in two variables
Keep checking whether the scripts completed or not after an interval say for every 1 to 2 seconds.
Kill the process which is not completed after a specific time say 30 seconds
Example:
sdist=$(ps -fu $USER|grep -v "grep"|grep "build_sdist.sh"| awk '{print $2}')
OR
sdist=$(ps -fu $USER|grep [b]uild_sdist.sh| awk '{print $2}')
deps=$(ps -fu $USER|grep -v "grep"|grep "cache_deps.sh"| awk '{print $2}')
Now use a while loop to check the status every after a certain interval or just check the status directly after 30 seconds like below
sleep 30
if grep "$sdist"; then
kill -8 $sdist
fi
if grep "$deps"; then
kill -8 $deps
fi
You can check the exit code status of the last executed command by checking the $? variable. Exit code 0 is a typical indication that the command completed successfully.
Exit codes can be set by using exit followed by the code number within a script.
Here's a previous question regarding the use of $? with more detail, but to simply check this value try:
echo "test";echo $?
# Example
echo 'copying the common packages'; ./build/build_sdist.sh;
if [ $? -ne 0 ]; then
echo "The last command exited with a non-zero code"
fi
[ $? -ne 0 ] Checks if the last executed commands error code is not equal to 0. This is also useful to ensure that any negative error codes generated such as -1 are captured.
The caveat of the above approach is that we have only checked against the last command executed and not the ... multiple operations.... that you mentioned, so we may have missed an error generated by a command executed before pip install.
Depending on the situation you could set -e within a subsequent script, which instructs the shell to exit the script at the first instance a command exits with a non-zero status.
Another option would be to perform a similar operation as the example within ./build/build_sdist.sh to check the exit code of each command. This would give you the most control as to when and how the script finishes and allows the script to set it's own exit code.

In a bash script, test error code from a called script

My bash script (init.sh) call another script (script.sh) and I want to test the error code from script.sh before doing any further action in init.sh.
I thought about testing it with $?, but it does not work
My init.sh is like the following:
#!/bin/bash
set -e
echo "Before call"
docker run -v $PWD:/t -w /t [command]
if [ $? == 1 ]; then
echo "Issue"
fi
echo "After call"
I only got the Before call from stdout and not the After call.
I know for a fact that if I execute docker run -v $PWD:/t -w /t [command] alone with wrong arguments, then echo $? will rightly display 1.
I was thinking that I do not catch the exit code from scrip.sh, but from somewhere else.
Any ideas?
You running the script with set -e. This means that if any command exits with a non zero status, bash will stop executing all subsequent lines. So here, if docker exits with status 1, the conditional that follows will not have a chance to run at all. Try this instead:
#!/bin/bash
set -e
echo "Before call"
if ! docker run -v $PWD:/t -w /t [command]; then
echo "Issue"
fi
echo "After call"
This runs the command inside the if test which suppresses the effect of set -e I described above and gives you a chance to catch the error. Note this is will also catch all non-zero statuses, not just 1.
Bash numeric comparison operator is -eq, and not ==...
So:
#!/bin/bash
set -e
echo "Before call"
docker run -v $PWD:/t -w /t [command]
if [ $? -eq 1 ]; then
echo "Issue"
fi
echo "After call"
set -e is generally a bad idea. Sure, it may seem like a good idea to have your script exit automatically in the event of an unexpected error, but the problem is that set -e and you may have different ideas about what constitutes a fatal error.
Instead, do your own error handling.
#!/bin/bash
echo "Before call"
docker run -v $PWD:/t -w /t [command]
docker_status=$?
if [ $docker_status != 0 ]; then
echo "docker returned: $docker_status"
exit $docker_status
fi
echo "After call"
In this simple code, I've somewhat redundantly saved the value of $? to another variable first. This ensures that it is preserved after you start executing other commands that examine, log, or otherwise process the value of $?. Also, I'm logging and exiting here on any non-zero status, not just 1. In theory, you might take different action for an exit status of 1 than for an exit status of 2, but here we take the same log-then-exit action for any error.

Catching all bad signals for called commands in Bash script

We are creating a bash script for a build server. We want to ensure that when we execute a bash command inside the script, it returns with a signal of 0. If it does not, we want execution to stop. Our solution so far is to do:
#some command
if [ $? -ne 0 ] ; then
#handle error
fi
after every command that could cause this problem. This makes the code quite long and doesn't seem very elegant. We could use a bash function, perhaps. Although working with $? can be a bit tricky, and we would still have to call the function after every command. Is there a better way? I've looked at the trap command but it seems to only do signal handling with the bash script I am writing, not any commands I call.
The robust, canonical way of doing this is:
#!/bin/bash
die() {
local ret=$?
echo >&2 "$*"
exit "$ret"
}
./configure || die "Project can't be configured"
make || die "Project doesn't build"
make install || die "Installation failed"
The fragile, convenient way of doing this is set -e:
#!/bin/bash
set -e # Script will exit in many (but not all) cases if a command fails
./configure
make
make install
or equivalently (with a custom error message):
#!/bin/bash
# Will be called for many (but not all) commands that fail
trap 'ret=$?; echo >&2 "Failure on line $LINENO, exiting."; exit $ret' ERR
./configure
make
make install
For the latter two, the script will not exit for any command that is part of a conditional statement or &&/||, so while:
backup() {
set -e
scp backup.tar.gz user#host:/backup
rm backup.tar.gz
}
backup
will correctly avoid executing rm if the transfer fails, later inserting a feature like this:
if backup
then
mail -s "Backup completed successfully" user#example.com
fi
will make the backup stop exiting on failure and accidentally delete backups.

Is it possible to check the output of previous step in the same script

The script runs two scripts depending on the output of the first script, i want to choose to run the script or not. For e.g
Mainscript.sh
./script1.sh....
is there a way to check output of script1.sh in mainscript.sh?
Because if output that there is connection between two system then i need to run the second script. Can i do it with python or i can do with bash only?
A common arrangement is to write your scripts so that programmatic operation is convenient. In concrete terms, that means that your script should return a zero exit code on success, nonzero otherwise. Then what you ask for is a simple matter of
script1 && script2
or in more complex cases
if script1; then
echo "$0: countdown to takeoff" >&2
script2
else
echo "$0: trouble occurred" >&2
script1 --reverse --undo --apologize
script3 || make clean
echo "$0: reverted everything" >&2
fi
You can access the last command exit code in $?. Also you can save its output.
#!/bin/sh
OUTPUT=`./script1.sh`
echo $?
echo $OUTPUT

Can you access the code of an exit command in a trap?

I understand that I can use $? to see the exit code of the last executed command, but what if I want to identify whether I have thrown my own "exit 0" or "exit 1"?
For example:
#!/bin/bash -e
trap "{ echo Exit code $?; exit; }" EXIT
exit 1
If I run this script, it prints out "Exit code 0" and then exits with exit code 1. Can I access the code in the trap, or am I just going about this the wrong way? In other words, I would like this simple script to print out "Exit code 1".
It's 0 because $? at the beginning of a script, where it is substituted due to the double quotes, is 0.
Try this instead:
trap '{ echo Exit code $?; exit; }' EXIT
Any process that terminates sets the $?, it means that it constantly will get overwritten. Save $? to a separately named var that is unique and echo that upon exit.
Edit
See Exit Shell Script Based on Process Exit Code

Resources