I'm trying to understand a shell/bash script and just wanted input on the use of $? in the code.
Its being used with a function call.
Function example:
function showerr { err=$1
if [ $err -ne 0 ]; then
echo `date` : "error!"
echo "stat : " $2
echo `date` : "stat: " $2
# alert email
prog=$0
uname=`whoami`
echo `date` : Sending email to ${ADDR_TO}
mailx -s "Error checking status " $ADDR_TO << EOF
+++++++++++++++++++++
stat = $2
util = $prog
host = $uname
+++++++++++++++++++++
Check $uname for details.
.
EOF
echo "Exiting program..."
exit 1
fi
}
Here are some statements calling showerr. I see some within a condition (using values like 1 or any number) and some just calling it $?.
if [[ $Res = *"FileNotFound"* ]]
then
echo `date` : Msg here
showerr 1 "Msg details here"
else
echo `date` : File: <filename> found.
fi
echo `date` : Msg detail here
flsz=`echo $size | cut -d'"' -f2`
showerr $? "error getting size for: (${flsz})"
$? is the exit code from the last command. See Shell Command Language: Special Parameters for the list of such special variables in POSIX shells.
The showerr function logs an error if its first parameter is not 0.
So:
./some_super_script_that_might_fail
showerr $? "SuperScript failed"
will only log something if ./some_super_script_that_might_fail's exit code is not 0 (which traditionally means that it failed).
showerr 1 "message"
will always log.
showerr 0 "message"
will never do anything.
Related
I wrote the following code :
echo "Choose between the following options:"
echo "1 - Create a new file"
echo "2 - Write in an existing file"
echo "3 - Change the path of a file"
echo "4 - Display a file"
echo "5 - Exit"
read number
while [ $number -ne 1 -o $number -ne 2 -o $number -ne 3 -o $number -ne 4 -o $number -ne 5 ]
do
echo "Enter a number between 1 and 5"
read number
done
if [ $number -eq 1 ]; then
echo "Enter a folder name"
read name
while [ -e $name ]
do
echo "The file name already exists enter a new name:"
read name
done
touch $name
fi
if [ $number -eq 2 ]; then
echo "Enter the folder name you want to edit :"
read name
while [ ! -f $name ]
do
echo "The file you are looking does not exist. Enter another file name :"
read name
done
echo "Enter what you want to put in the file :"
read input
echo $input >> $name
fi
if [ $number -eq 3 ]; then
echo "Enter the folder name :"
read name
while [ ! -f $name ]
do
echo "The file you are looking does not exist. Enter another file name :"
read name
done
if [ $number -eq 4 ]; then
echo "Enter the folder name you want to see :"
read name
while [ ! -f $name ]
do
echo "The file you are looking does not exist. Enter another file name :"
read name
done
cat $name
fi
if [ $number -eq 5 ]; then
exit 0
fi
The code works just fine, but on the first condition :
while [ $number -ne 1 -o $number -ne 2 -o $number -ne 3 -o $number -ne 4 -o $number -ne 5 ]
I would like it to work to whatever number or string I put.
For example, if I put hello the program will crash.
Can someone tell me what should my first condition be?
Thank you for your help. And forgive me if my question is not in the rules of the forum (I just subscribed).
Your script says:
while [ $number -ne 1 -o $number -ne 2 -o $number -ne 3 -o $number -ne 4 -o $number -ne 5 ]
So, if $number is 1, it's not equal to 2. And if it's 2, it's not equal to 1. This will always evaluate as true, so you'll never exit the loop.
A variety of options exist that will be compatible with a numeric value and still gracefully handle non-numeric input. The following uses a basic regular expression to determine whether input is a digit from 1 to 5:
while read number && ! expr "$number" : '[1-5]$' >/dev/null; do
echo "Try again" >&2
done
You would probably be better off, though, using a case statement:
while read number; do
case "$number" in
1) function_1 ;;
2) function_2 ;;
... etc
*) echo "Invalid input, please try again." >&2; continue ;;
esac
break
done
The case statement is a more graceful way of expressing what might otherwise be achieved using if..elif..elif..fi:
while read number && ! expr "$number" : '[1-5]$' >/dev/null; do
echo "Try again" >&2
done
if [ "$number" = 1 ]; then
: do_something
elif [ "$number" = 2 ]; then
: do_something
elif [ "$number" = 3 ]; then
: do_something
elif [ "$number" = 4 ]; then
: do_something
elif [ "$number" = 5 ]; then
: do_something
else
echo "What am I doing?" >&2
fi
While this construct technically works, it's inelegant and harder to read. Much better to put your functionality into functions which get called from a case statement.
Note that it's always a good idea to quote your variables within a script like this. Do you know what happens with unquoted variables? If not, then quote your variables. :)
I would strongly suggest structuring your code with a case statement:
case $number in
1) code_for_1;;
2) code_for_2;;
...
*) echo "Invalid number" >&2;;
esac
If you wish to repeat (I would actually recommend taking the number as a command line argument instead of reading from stdin and aborting on an error), you could simply do:
while read number; do
case $number in
...
*) echo 'Invalid number' >&2; continue;;
esac
break
done
And write code_for_{1,2,3,4,5} as functions to factor out the logic. For example:
create_file() {
echo "Enter a file name"
while read name; do
if test -e "$name"; then
echo "The file $name already exists enter a new name" >&2
continue
fi
touch "$name"
break
done
}
while read number; do
case $number in
1) create_file;;
...
*) echo 'Invalid number' >&2; continue;;
esac
break
done
im trying to check if my script ran correctly if not, to echo a message, however when i use this if statement, it produces an error on line '9' (if [ $? -eq 0 ]) Saying that a ' is missing.
#!/bin/bash
name=$1
if ["$name" = ""]
then
echo -n "Enter a name to search for: "
read name
fi
if [ $? -eq 0 ]
then
echo "Incorrect Input"
fi
if ["$name" = ""]
is wrong because you must have a space between the [ and the expression (and before the ] as well).
There's nothing obviously wrong with the syntax of
if [ $? -eq 0 ]
but it's always dubious to check exit codes with arithmetic, since that's what if does directly. If your script is as you show it above, the second if statement should always be true. The fact that the previous if statement's expression was false doesn't matter, because the if statement yields zero if no condition tested true. For example:
$ if false; then echo hi; fi; echo $?
0
I am attempting to make a script that will check to see if there is any tyext within a file. I have developed the following script. I have made it check to see if there is exactly 2 arguments, see if the file exists, but I am having trouble checking the file for text within it. The code is as follows:
#!/bin/ksh
#check if number of arguments are 2
if [ $# -ne 2 ]; then
echo "Does not equal two arguments"
echo "Usage $0 inputfile outputfile"
exit 1
fi
#check if input file exists
if [ ! -f $1 ]; then
echo "$1 not found!"
exit 1
fi
#Check if input file is null
#This next block of code is where the issue is
if [ grep -q $1 -eq 0 ]; then
echo "$1 must have text within the file"
exit 1
fi
Any help would be appreciated
test's "-s" option checks if the file is empty -- see manual. So your last chunk would become
#Check if input file is null
#This next block of code is where the issue is
if [ ! -s $1 ]; then
echo "$1 must have text within the file"
exit 1
fi
Try using stat
stat -c %s filename
I have the below script that is expected to work when the user invokes sh <scriptName> <propertyfile> It does work when I provide this at the dollar prompt. However, I am having two issues with the script.
If I provide just one argument, ie if I do - sh <scriptName>, I see the below error -
my-llt-utvsg$ sh temp.sh
Usage temp.sh
When I do -help, I see the below error -
my-llt-utvsg$ sh tmp.sh -help
-help does not exist
What am I doing wrong? Can someone please advise? I am a software developer that very rarely needs to do shell scripting, so please go easy on me ;)
#!/bin/bash
FILE="system.properties"
FILE=$1
if [ ! -f $FILE ];
then
echo "$FILE does not exist"
exit
fi
usage ()
{
echo "Usage $0 $FILE"
exit
}
if [ "$#" -ne 1 ]
then
usage
fi
if [ "$1" = "-help" ] ; then
echo ""
echo '############ HELP PROPERTIES ############ '
echo ""
echo 'Blah.'
exit
The reason your
if [ "$1" = "-help" ] ; then
check is not working is that it only checks $1 or the first argument.
Try instead:
for var in "$#"
do
if [ "$var" = "-help" ] ; then
echo ""
echo '############ HELP PROPERTIES ############ '
echo ""
echo 'Blah.'
fi
done
Which will loop over each argument and so will run if any of them are -help.
Try this as well:
#!/bin/bash
FILES=()
function show_help_info_and_exit {
echo ""
echo '############ HELP PROPERTIES ############ '
echo ""
echo 'Blah.'
exit
}
function show_usage_and_exit {
echo "Usage: $0 file"
exit
}
for __; do
if [[ $__ == -help ]]; then
show_help_info_and_exit
elif [[ -f $__ ]]; then
FILES+=("$__")
else
echo "Invalid argument or file does not exist: $__"
show_usage_and_exit
fi
done
if [[ ${#FILES[#]} -ne 1 ]]; then
echo "Invalid number of file arguments."
show_usage_and_exit
fi
echo "$FILES"
I have been trying to execute the following UNIX shell script which is not working.
I am running it by KornShell (ksh).
echo $?;
if [ $? -ne 0 ]
then
failed $LINENO-2 $5 $6
fi
failed()
{
echo "$0 failed at line number $1";
echo "moving $2 to failed folder"
}
This is giving an error saying Syntax error:then unexpected.. Basically I have to check for the last executed ksh script's highest/last statement's return code and if it is not equal to zero I have to call function failed with the given parameters. I tried putting semicolon before then but that also did not work.
Can you please help?
Edit1: Based on the inputs I changed code. Still the same problem exists.
ksh ../prescript/Pre_process $1 $2 $3
rc=$?;
if [[ $rc -ne 0 ]];then
echo "failed";
exit 1;
Edit2:
It is working for the then part by using double squared brackets. I feel I used code of bash script for ksh. I am facing problem in function call of failed. Please let me know appropriate way of function call in ksh for this example
This looks like bash rather than ksh
failed() {
echo "$0 failed at line number $1";
echo "moving $2 to failed folder"
}
if [[ $? -ne 0 ]]
then
failed $LINENO-2 $5 $6
fi
You need to be careful. The first operation on $? will usually clear it so that your if won't work anyway.
You would be better off using:
rc=$?
echo $rc
if [ $rc -ne 0 ]
:
Other than that, it works fine for me:
$ grep 1 /dev/null
$ if [ $? -ne 0 ]
> then
> echo xx
> fi
xx
$ grep 1 /dev/null
$ echo $?;
1
$ if [ $? -ne 0 ]
> then
> echo yy
> fi
$ _
Note the lack of output in the last one. That's because the echo has sucked up the return value and overwritten it (since the echo was successful).
As an aside, you should let us know which UNIX and which ksh you're actually using. My working version is ksh93 under Ubuntu. Your mileage may vary if you're using a lesser version.
It looks like, from your update, your only problem now is the function call. That's most likely because you're defining it after using it. The script:
grep 1 /dev/null
rc=$?
if [ $rc -ne 0 ]
then
failed $rc
fi
failed()
{
echo Return code was $1
}
produces:
qq.ksh[6]: failed: not found
while:
failed()
{
echo Return code was $1
}
grep 1 /dev/null
rc=$?
if [ $rc -ne 0 ]
then
failed $rc
fi
produces
Return code was 1
you are missing semicolons at the end of the lines:
if [ $? -ne 0]; then
# …