I have a program which returns always zero exit code, even in case of an internal error. In case of an error there is additional output to standard output like:
# always-zero-exit
Error: Line: 1, Column: 1
some further scary error description....
Can someone please advice how to make a short bash workaround like the one below:
# always-zero-exit > search-for-string-'Error'-and-returns-non-zero-if-found
As Biffen suggested in the comment, use ! grep ERROR_PATTERN.
Example:
# Tiny test command that exit with status 0 and
# prints errors into STDOUT:
echo 'Error: Line: 1, Column: 1' > out.log
! grep -q 'Error' out.log
echo $?
# Prints: 1
# Same, no errors:
echo 'Line: 1, Column: 1' > out.log
! grep -q 'Error' out.log
echo $?
# Prints: 0
You may want to use more complex error message processing, for example:
! grep -Pqi '(error|fail|exception)' out.log
Here, grep uses the following options:
-P : Use Perl regexes.
-i : Use case-insensitive matching.
-q : Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found.
SEE ALSO:
grep manual
Related
I am trying to find if the word in the file.
If the word is found, it will print 'Found'.
Else 'Not Found'.
But in the process of trying I am confused by the word count of bash.
Can someone help me?
Thank you
#!/bin/bash
a=`grep -c -w $1 /file.txt`
if [ $a > 0 ]
then
echo Found
else
echo Not Found
fi
I suggest:
if grep -q -w "$1" /file.txt; then
From man grep:
Normally the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred. However, if the -q or --quiet or --silent is used and a line is selected, the exit status is 0 even if an error occurred.
Could you please try following, in place of text give your text which are looking into Input_fie, where Input_file is your actual file where you are looking.
if grep -q "text" Input_file
then
echo "text found."
else
echo "Text NOT found"
fi
I am trying to do something similar to "try.. catch" with bash, for which I read from this post that a good option to somehow replicate try/catch is to use the || and && operators.
In my case, I have a piece of code supposed to zip some files, but the zip is actually empty, so it throw an error:
zip -v OUTPUT.zip file1 file2 >> $LOGFILE 2>&1
Then in the LOGFILE, I see:
zip error: Nothing to do! (OUTPUT.zip)
zip warning: OUTPUT.zip not found or empty
...(continued error message)
So I do this instead, to "catch the error"
{ zip -v OUTPUT.zip file1 file2 >> $LOGFILE 2>&1 } || { printf "Error while zipping!" >> $LOGFILE && exit 1 }
..which partially works. It does exit the code, but doesn't do the printf command (or at least I can't see it in the LOGFILE).
Also, although it encounters the "exit 1" command (on line 115), I also have the message (line 120 is my last line):
line 120: syntax error: unexpected end of file
What is wrong in my command? Why doesn't it do the print, and why the "unexpected end of file" message? Sorry if this question is more related to general bash programming than to the use of || &&, but I didn't know how to categorize this otherwise.
Thanks a lot!
Within braces, you must terminate all commands with a semi-colon, as per the following transcript (you can see on the last line bash is waiting for more command to be typed in):
pax> { false; } || echo x;
x
pax> { false } || echo x;
+++> _
You also don't need to "brace up" a simple command, so the correct thing in your case would be:
zip -v OUTPUT.zip file1 file2 >> $LOGFILE 2>&1 || { echo "Error while zipping!" >> $LOGFILE ; exit 1 }
I've also used echo rather than printf, on the assumption you'll want a newline character at the end of the file, and made the exit unconditional on the success or otherwise of printf/echo.
I want to extract a matched regex from this file:
abc
de
{my_pattern.global} # want to extract my_pattern.global
# without curly brackets
123
and assign it to a variable in a shell script:
#!/bin/bash
l_config_file="my_file.cfg"
l_extracted_pattern=""
l_match_pattern="(?<={).+\.global(?=})"
l_my_dir=$(pwd)
echo "grep -oP '$l_match_pattern' $l_my_dir/$l_config_file"
echo "debug 1 - exit code: $?"
grep -oP '$l_match_pattern' $l_my_dir/$l_config_file
echo "debug 2 - exit code: $?"
sh -c "grep -oP '$l_match_pattern' $l_my_dir/$l_config_file"
echo "debug 3 - exit code: $?"
$l_extracted_pattern = "$(sh -c "grep -oP '$l_match_pattern' $l_my_dir/$l_config_file")"
echo "debug 4 - exit code: $?"
echo $l_extracted_pattern
Output:
grep -oP '(?<={).+\.global(?=})' /tmp/my_file.cfg
debug 1 - exit code: 0
debug 2 - exit code: 1
my_pattern.global
debug 3 - exit code: 0
./sto.sh: line 14: =: command not found.
debug 4 - exit code: 127
As you can see, the grep command works well (when executed via sh -c) but fails when trying to assign the output to the variable $l_extracted_pattern with exit code 127. That means the shell doesn't recognise the command. I suspect the regex is cause of the trouble here, but couldn't figure out what in particular. What's going wrong?
Even though I assigned it before already :
l_extracted_pattern=""
and tried to overwrite it later:
$l_extracted_pattern = "$(sh -c "grep -oP '$l_match_pattern' $l_my_dir/$l_config_file")"
That was a mistake. Apparently no variable assignment in bash may contain the $ before the variable name - even not when instantiated already before. Changed it to:
l_extracted_pattern = "$(sh -c "grep -oP '$l_match_pattern' $l_my_dir/$l_config_file")"
I have a bash shell script doing sth like
#!/bin/bash
# construct regex from input
# set FILE according to input file
egrep "${regex}" "${FILE}" | doing stuff | sort
I want this script to write the output (a list of new line separated matches) of the command to stdout if matches are found (which it is doing). If no matches are found it needs to write out an error message to stderr and exit with exit status 3.
I tried this
#!/bin/bash
# construct regex from input
# set FILE according to input file
function check () {
if ! read > /dev/null
then
echo "error message" 1>&2
exit 3
fi
}
egrep "${regex}" "${FILE}" | doing stuff |
sort | tee >(check)
Now the correct error message is written out but the exit status "cannot escape the subshell"; the outer script is still exiting with exit status 0.
I also tried sth like
#!/bin/bash
# construct regex from input
# set FILE according to input file
if ! egrep "${regex}" "${FILE}" | doing stuff | sort
then
echo "error message" 1>&2
exit 3
fi
But here I have the problem that one of the commands in the pipe (especially sort) exits with an exit status 0
How can I get my desired exit status 3 and error message while keeping the output for normal execution and without doing all the stuff twice?
EDIT:
I can solve the problem by using
#!/bin/bash
# construct regex from input
# set FILE according to input file
if ! egrep "${regex}" "${FILE}" | doing stuff | sort | grep .
then
echo "error message" 1>&2
exit 3
fi
However I am not sure this is the best way since pipes are working in parallel...
I would use the PIPESTATUS to check the exit code of egrep:
#!/bin/bash
# construct regex from input
# set FILE according to input file
egrep "${regex}" "${FILE}" | doing stuff | sort
if [[ ${PIPESTATUS[0] != 0 ]]; then
echo "error message" 1>&2
exit 3
fi
Some context:
${PIPESTATUS[#]} is just an array wich contains the exit code of every program you chained up. $? will just give you the exit code of the last command in the pipe.
Never coded on bash but need something urgent. Sorry if this is not the norm but would really like to get some help.
I have some messages that are thrown to stdout, Depending on the message type (the message is a string with the word "found") I need the bash script to beep.
So far I've come up with this.
output=$(command 1) # getting stdout stream?
while [ true ]; do
if [ "$output" = "found" ]; then # if the stdout has the word "found"
echo $(echo -e '\a') # this makes the beep sound
fi
done
I'm not sure where/how to add grep or awk command to check for the string that has the word "found" and only return "found" so that in the if condition it can check against that word.
Thanks!
You can do something as simple as:
command | grep -q 'found' && echo -e '\a'
If the output of command contains the text "found", then grep will return with a zero exit status, so the echo command will be executed, causing the beep.
If the output does not contain "found", grep will exit with status 1, and will not result in the echo.
Depending on what you need to make the beep work, just replace anything after the &&. The general syntax would be something like:
command | grep -q "$SEARCH" && command_if_found || command_if_not_found