Conditional logic in Makefile from Grep exit codes - makefile

I'm writing a connivence function in a Makefile and I'm having some trouble capturing and making decisions returned by a grep status code.
I'm aware that a command that exits with a non-zero status will terminate Make. And I also know that make, by default, spawns an sh shell, so I'm not sure if that's complicating things.
I'm running this command: golint | grep -v "comment on exported" which returns 1 if the command completes successfully (there is no output from grep; all output is filtered) and 0 if there is still output left unfiltered. Not sure why grep is counterintuitive this way, but that's besides the point.
I want to echo 'No liniting issues' on success and just print the unfiltered lines on failure.
I thought any one of these permutations would work:
lint:
# Will never print 'No linting issues'
! golint | grep -v "comment on exported" || echo 'No linting issues'
! `golint | grep -v "comment on exported"` || echo 'No linting issues'
! (golint | grep -v "comment on exported") || echo 'No linting issues'
# Exits with syntax error: unexpected end of file
if [ $(golint | grep -v "comment on exported") -ne 0 ]; then
echo 'No linting issues'
fi
This seems to be such a simple thing, so this question is coming more out of frustration to get it to work than anything else.
I appreciate the help!

Related

Previous command output on mac OS X

I have below script. When I run each line in iTerm on MacOs, every command works. But if i save this as a shell script, it says "!! command not found". I have tried #!/bin/bash. But still it doesn't work.
#!/bin/sh
./ongoingShellScript.sh
if !! | grep "errors: 0"
then
echo Success
else
echo Failure
fi
I could have done
if ./ongoingShellScript.sh | grep "errors: 0"
But in this case, output of ongoingShellScript won't be printed in realtime.
What am i doing here ?
Thank you in advance
GV
!! doesn't refer to previous output -- it runs the whole command over again, and thus generates a new set of output. Moreover, the featureset it comes from -- called "history expansion" -- is an interactive extension turned off by default during script execution.
If you want to print status for the user while testing stdout for a string, the easy tool for the job is grep:
if ./ongoingShellScript.sh | tee /dev/stderr | grep -q "errors: 0"; then
echo "Success" >&2
else
echo "Failure" >&2
fi
...assuming that errors: 0 comes at the end of output, and thus that it's acceptable for tee to exit as soon as grep has seen this string.

Install Check Script that checks Profiles -P for a specific profile

I am trying to write up a instal check script that runs profiles -Pand exits based on the response.
We use a profile from meraki which the output looks like so (if installed):
_computerlevel[1] attribute: profileIdentifier: com.meraki.sm.mdm
There are 1 configuration profiles installed
Is there a way to check this out put for this exact response?
I was thinking something like:
#!/bin/bash
output=profiles -P
if [ output = com.meraki.sm.mdm ]; then
exit 0;
else
exit 1;
Any ideas?
Try the following:
#!/bin/bash
if sudo profiles -P | egrep -q ': com.meraki.sm.mdm$'; then
exit 0
else
exit 1
fi
Output from sudo profiles -P (note that profiles always requires root privileges) is sent via a pipe (|) to egrep; the two commands form a pipeline.
egrep -q ': com.meraki.sm.mdm$' searches through profile's output:
-q (quiet) option produces no output and simply signals via its exit code whether a match was found (0) or not (1).
': com.meraki.sm.mdm$' is a regular expression that matches string 'com.meraki.sm.mdm' found at the end of the line ($), preceded by ': '.
(egrepis the same asgrep -E` - it activates support for extended regular expressions - not strictly necessary here, but generally advisable for fewer surprises).
The if statement evaluates to true if the pipeline returns exit code 0, and to false otherwise (nonzero). Note that by default it is the last command in the pipeline whose exit code determines the pipeline's overall exit code.
Incidentally, if all you wanted to do is to have your script reflect whether the string was found or not (i.e., if you don't need to take further action inside your script), the following would suffice:
sudo profiles -P | egrep -q ': com.meraki.sm.mdm$'
exit $? # Special variable `$?` contains the most recent command's exit code
If you wanted to exit your script right after in the event of failure only:
sudo profiles -P | egrep -q ': com.meraki.sm.mdm$' || exit
# Alternative, with error message:
sudo profiles -P | egrep -q ': com.meraki.sm.mdm$' ||
{ ec=$?; echo 'Profile not installed.' >&2; exit $ec; }
Conversely, if you wanted to exit right after in the event of success:
sudo profiles -P | egrep -q ': com.meraki.sm.mdm$' && exit

Not able to force exit on Jenkins Build

I've been having a lot of trouble with this so here goes.
I have a Jenkins build that executes the following shell script:
#!/bin/sh -x
if [ 'grep -c "It misses" log' -gt 0 ];
then exit 1;
fi
I know that the grep returns 1 when it finds something and technically Jenkins should mark the build as failed on a non-zero exit, but the jenkins still marks it as a success.
The console output for the jenkins build when running the script is:
Started by user bla
[project_name] $ /bin/sh -x /var/tmp/hudson41276.sh
+ [ grep -c "It misses" log -gt 0 ]
Finished: SUCCESS
Could anybody give me a hand and point out what I'm missing here?
Thanks,
CJ
If I understand right, you want the job to fail if "It misses" is not found in file "log". You can do this by not using the -c option of grep, just redirect the output like this:
grep "It misses" log > /dev/null
Grep will return 0 if it finds the phrase, and the job will succeed. If it does not find the phrase, grep will return 1, and the job will fail. If you want it the other way around (fail if it does find the phrase) just use grep -v. $? is your friend when you want to be sure of the exit status of a shell command.
Try this:
#!/bin/sh
set -e
grep -c "It misses" log
set -e: Exit at the first error.
grep -c 'arg': Exit 1 if nothing was grepped.
The problem is with your script, not Jenkins. The part of your script where you attempt to compare the exit code of grep looks like this:
if [ 'grep -c "It misses" log' -gt 0 ] ...
This will not even execute grep. In fact, it is simply comparing a string to a number.
You were probably attempting to do:
if [ `grep -c "It misses" log` -gt 0 ] ...
Note the use of backticks (`). Shell will execute grep and replace the backticks with the output of grep.
Bonus item: the condition in the if statement is actually a command that gets executed and its exit code determines where the execution will continue. So... why not use the grep command and it's useful exit code as the condition? (grep will exit with code 0 when it finds matches.)
if grep "It misses" log; then
exit 1
fi
It's shorter, much more readable and ever performs better because it does not need to execute so many commands.
Such a short if statement could even be replaced with a one-liner:
grep "It misses" log && exit 1
By default jenkins start shell with -e, so it exists at first error.
You could turn it off by
set +e
do failing task..

check for error with shell script with multiple commands on one line [duplicate]

This question already has answers here:
Piping command output to tee but also save exit code of command [duplicate]
(4 answers)
Closed 9 years ago.
I'm trying to catch the error code of a failed command in my shell script on Linux. In this case my ffprobe command:
#!/bin/sh
videoduration=$(ffprobe -loglevel error -show_format myfile.avi | grep duration | cut -d= -f2)
if [ $? -ne 0 ]; then
echo "ERROR"
exit 1
fi
echo $videoduration
If I change that command to give a bogus file name:
#!/bin/sh
videoduration=$(ffprobe -loglevel error -show_format myfile.av | grep duration | cut -d= -f2)
if [ $? -ne 0 ]; then
echo "ERROR"
exit 1
fi
echo $videoduration
The error code is useless here because technically the status code is still 0. The code will still have a successful grep and cut. How can I keep this command in a single variable but exit with error if ffprobe command fails?
EDIT: I'd prefer a non shell specific answer if there is one. Also the proposed duplicate covers a similar case but the only potential option here is to create a temp file like so:
f=`mktemp`
(ffprobe ...; echo $?>$f) | ...
e=`cat $f` #error in variable e
rm $f
Seems like a hack creating a temp file? If this is the only option how would I store this in a variable?
The problem is that even though the ffprobe command fails, the cut does not and returns a zero exitcode. The exit status of a pipe is the exit status of the last command, unless your shell has means to change this behaviour to return the exit status of the first command to fail. You can do this with set -o pipefail in bash/ksh:
$ false | cut -d= -f2; echo $?
0
$ set -o pipefail
$ false | cut -d= -f2; echo $?
1

Bash: how to interrupt this script when there's a CTRL-C?

I wrote a tiny Bash script to find all the Mercurial changesets (starting from the tip) that contains the string passed in argument:
#!/bin/bash
CNT=$(hg tip | awk '{ print $2 }' | head -c 3)
while [ $CNT -gt 0 ]
do
echo rev $CNT
hg log -v -r$CNT | grep $1
let CNT=CNT-1
done
If I interrupt it by hitting ctrl-c, more often than not the command currently executed is "hg log" and it's that command that gets interrupted, but then my script continues.
I was then thinking of checking the return status of "hg log", but because I'm piping it into grep I'm not too sure as to how to go about it...
How should I go about exiting this script when it is interrupted? (btw I don't know if that script is good at all for what I want to do but it does the job and anyway I'm interested in the "interrupted" issue)
Place at the beginning of your script: trap 'echo interrupted; exit' INT
Edit: As noted in comments below, probably doesn't work for the OP's program due to the pipe. The $PIPESTATUS solution works, but it might be simpler to set the script to exit if any program in the pipe exits with an error status: set -e -o pipefail
Rewrite your script like this, using the $PIPESTATUS array to check for a failure:
#!/bin/bash
CNT=$(hg tip | awk '{ print $2 }' | head -c 3)
while [ $CNT -gt 0 ]
do
echo rev $CNT
hg log -v -r$CNT | grep $1
if [ 0 -ne ${PIPESTATUS[0]} ] ; then
echo hg failed
exit
fi
let CNT=CNT-1
done
The $PIPESTATUS variable will allow you to check the results of every member of the pipe.

Resources