bash if greater than or equal to error - bash

With the bash script below I am getting an error;
line 16: [: : integer expression expected but I can't figure out why? The error lies in if [ "$(log_date)" -le "$days_in_ms" ]; then Can anyone help and explain as BASH if statements confuse me
#!/bin/bash
region="eu-west-1"
retention_days="28"
days_in_ms="$(date +%s%3N --date=-"$retention_days"+days)"
log_date () {
aws logs describe-log-streams --region $region --log-group-name "$groups" | jq -r '.logStreams[].lastEventTimestamp' > /dev/null 2>&1
}
log_name () {
aws logs describe-log-streams --region $region --log-group-name "$groups" | jq -r '.logStreams[].logStreamName' > /dev/null 2>&1
}
mapfile -t logGroups < <(aws logs describe-log-groups --region $region | jq -r '.logGroups[].logGroupName') > /dev/null 2>&1
for groups in "${logGroups[#]}"; do
if [ "$(log_date)" -le "$days_in_ms" ]; then
log_name
fi
done

What's Happening
Note the details of the error message:
[: : integer expression expected
See the blank before the second :? That's where the value that [ is trying to operate on would be, if there were one. It's blank, meaning something [ was told would be a number is not there at all.
To provide an example of how this works:
$ [ foo -ge 1 ]
-bash: [: foo: integer expression expected
Note that the foo is given in the same position where you have a blank. Thus, a blank value is being parsed as a number.
Why It's Happening
Your log_date function does not return any output, because of its >/dev/null. Consequently, your code tries to parse the empty string it returns as a number, and (correctly) complains that it's getting an empty string in a position where an integer is expected.
In the future, run set -x to enable logging of each command before it's run, or invoke your script with bash -x yourscript when debugging, to identify these issues.

Related

Makefile: Interpolate variable uuid in command

I want to write a command so it runs using a randomly generated uuid each time, interpolating this variable into the command.
I'm in MacOS, so I can use the uuidgen command
❯ uuidgen
E4BC7525-1EC7-4338-8F4F-8DA268CB7051
I want to interpolate this value as part of my command like that:
send-test-sqs-message: ## Send test sqs message to generate an email
aws sqs send-message "{\"identifier\":$(uuidgen), ..." --output table | cat
But the output when running make send-test-sqs-message shows that "identifier" is empty.
Running the command with set -x provides this extra output which doesn't look relevant:
+_p9k_preexec1:1> _p9k_restore_special_params +_p9k_restore_special_params:1> (( ! 0 )) +_p9k_restore_special_params:7> (( ! 0 )) +_p9k_restore_special_params:11> (( ! 0 )) +_p9k_preexec1:2> unset __p9k_trapint +_p9k_preexec1:3> trap - INT +omz_termsupport_preexec:1> [[ '' != true ]]
How can this be fixed?

syntax error: invalid arithmetic operator (error token is "

my script refuses to work under cron, but works fine while executing manually
#!/bin/bash
LOGFILE=/opt/xxx/scripts/rc.log
fUpMail() {
echo -e "Hello!\n\n$1 xx\n\nBest regards,\n\nCheck LLC 2k18" | mailx -s "$1 Rates were not imported" smone#smth.com
}
curDate=`date +%Y-%m-%d`
#postgres expression output being assigned to a variable
rateQ=`PGPASSWORD=xxxxxx psql -t -h xxx.xxx.228.134 -p 5433 -d axx2 -U axxx2bo << EOF
SELECT COUNT(id) FROM quote WHERE f_date = '$curDate'
EOF`
#same for demodb
rateDemo=`PGPASSWORD=xxx psql -t -h xx.xxx.42.14 -p 5432 -d axxxo -U acxxxxbo << EOF
SELECT COUNT(id) FROM quote WHERE f_date = '$curDate'
EOF`
#logging
printf "\n`date +%H:%M:%S` $curDate $rateQ $rateDemo\n" >> $LOGFILE
#check if rate value is not null
if [[ $(($rateQ)) != 0 ]] && [[ $(($rateDemo)) != 0 ]];
then
#posting a commentary into jira
curl -u xxx-support-bot:Rzq-xxx-xxx-gch -X POST --data '{"body": "'"$rateQ"' LIVE rates for '"$curDate"' were imported automatically'"\n"''"$rateDemo"' DEMO rates for '"$curDate"' were imported automatically"}' -H "Content-type: application/json" https://jira.in.xxx.com:443/rest/api/2/issue/xxxxxx-1024/comment >> $LOGFILE
else
#if rates were not imported
if [[ $(($rateQ)) == 0 ]];
then
echo "looks like LIVE rates for $curDate were not imported, please check manually!"
#sending a letter
fUpMail 'LIVE'
fi
if [[ $(($rateDemo)) == 0 ]];
then
echo "looks like DEMO rates for $curDate were not imported, please check manually!"
fUpMail 'DEMO'
fi
fi
cron sends following message:
/opt/xxx/scripts/ratecheck.sh: line 25: Timing is on.
6543
Time: 4.555 ms: syntax error: invalid arithmetic operator (error token is ".
6543
Time: 4.555 ms")
line 25 is
if [[ $(($rateQ)) != 0 ]] && [[ $(($rateDemo)) != 0 ]];
Could please someone help explaining what's wrong here?
You're getting more than a plain number back from psql and this is interfering with the type conversion you're doing. I think you can remove the extra output like this:
rateQ=$(PGPASSWORD=xxxxxx psql -t -h xxx.xxx.228.134 -p 5433 -d axx2 -U axxx2bo -q -c "SELECT COUNT(id) FROM quote WHERE f_date = '$curDate'")
rateDemo=$(PGPASSWORD=xxx psql -t -h xx.xxx.42.14 -p 5432 -d axxxo -U acxxxxbo -q -c "SELECT COUNT(id) FROM quote WHERE f_date = '$curDate'")
Note the addition of the -q flag:
-q
--quiet
Specifies that psql should do its work quietly. By default, it prints welcome messages and various informational output. If this option is used, none of this happens. This is useful with the -c option. This is equivalent to setting the variable QUIET to on.
https://www.postgresql.org/docs/9.0/app-psql.html
I also replaced your old-fashioned backticks with $() and put the SQL query into an argument.
If that doesn’t silence the additional output, you may also need to edit ~/.psqlrc for the user running the cron job and ensure there is no \timing line.

jq suppress parsing error for 404 json files

echo $(curl -s -u user:pwd "http://site/file.json" | jq -e -r '.data[]? | select(.state == "Active") | if . == null then "Installing" elif . == "Active" then "Active" else "Installing" end')
Following is the error:
parse error: Invalid numeric literal at line 2, column 0
In a scenario when file.json doesn't exist 404 page is returned and jq is throwing a parsing error. In such case I want to return string "Installing". Tried many things but nothing is working out, please help.
Write the response into a variable:
# -f makes curl return an error in case of HTTP error.
# Check "man curl" on how reliable this is.
response="$(curl -f ...)"
if [ $? -ne 0 ] ; then
echo "Installing"
else
jq FILTER <<< "${response}"
fi

bash script - unable to evaluate variable to string correctly

Trying to debug my bash script. What's wrong with my syntax here? I'm trying to evaluate a parameter entered by the user and based on that run one of my IF-THEN statements. However, I'm getting a command not found.
Here's my script thus far:
if [[ $# != 4 ]]; then
echo "Usage: ./test.sh <ABC|XYZ> <owner> <db> <TARGETHOST>" 2>&1
exit 1
fi
case $1 in
ABC|XYZ)
filename="get-$1.sql"
;;
*)echo "Must enter ABC or XYZ"
exit 1
;;
esac
export OWNER=$2
export DB=$3
export HOST_NM=$4
export PORT=5432
export LOG="test-$1.log"
PSQL=`which psql`
if [[$1=="ABC"]]; then
RUNCLI=$("$PSQL" -h $HOST_NM -p $PORT -U $OWNER $DB -F $'\t' --no-align -f get-$1.sql | tee >> $LOG)
exit 1
else
echo "Error running report ..."
fi
if [[$1=="XYZ"]]; then
RUNCLI2=$("$PSQL" -h $HOST_NM -p $PORT -U $OWNER $DB -a -f get-$1.sql | tee >> $LOG)
exit 1
else
echo "Error running report ..."
fi
Error:
./test.sh: line 41: [[XYZ==ABC]]: command not found
Error running report ...
./test.sh: line 51: [[XYZ==XYZ]]: command not found
Error running report ...
Although the question is already answered in the comment section I want to give an answer and share some knowledge which is not obvious (at least it was not for me).
The if in bash just checks the return code of the following command, which means that instead of if [ condition ]... or if [[ condition ]]... you could also write if ./configure && make....
[ and [[ are commands or shell-built-ins, respectively, as well and not part of the if syntax. An which [ for instance returns /bin/[.
At this point it is obvious that you need spaces between the brackets and the condition since it is just just a set of parameters passed to a command.
If you have this in mind, you will never forget the spaces again.

Error in two scripts: "unary operator expected" and "integer expression expected"

I wrote two scripts which try to do the same action in two different ways, but I get errors each time I run those. Kindly requesting your help to correct my scripts and to improve my knowledge as well. All I am trying to do the vps setup in a single script. Following two scripts are just a portion of it which get errors each time.
1) Script to set hostname through cpanel xml-api for a vps in openvz node
cat vpstest.sh
#/bin/bash
hostname_status=`curl -sku root:PASSWORDHERE "https://ip.x.x.x:2087/xml-api/sethostname?hostname=server.domain.com" | awk -F"[<>]" '/status/{print $3}' | head -n1`
if [ $hostname_status -eq 1 ]; then
echo "Hostname set"
else
echo "Failed setting hostname"
fi
Output:
# ./vpstest.sh
./vpstest.sh: line 3: [: -eq: unary operator expected
Failed setting hostname
2) Script to set hostname via command line in an openvz node
cat vpstest1.sh
#!/bin/bash
hostname_status=`vzctl set containerID --hostname server.domain.com --save`
if [ "$hostname_status" -eq 1 ] ; then
echo "Hostname set"
else
echo "Failed setting hostname"
fi
Output:
# ./vpstest1.sh
./vpstest1.sh: line 3: [: CT configuration saved to /etc/vz/conf/containerID.conf: integer expression expected
Failed setting hostname
Can someone help to clear these errors?
First, the output of vzctl set containerID --hostname server.domain.com --save seems not be an integer value whereas -eq is only provided to do comparisons between integers values.
This would explain the following error :
integer expression expected
Then, you should read this reminder about the necessity (or not) to protect your variables with double quotes.
This would explain the following error, you could use something like :
./vpstest.sh: line 3: [: -eq: unary operator expected
If you want to check the status of a command :
command >/dev/null 2>&1 && echo "success" || echo "fail"
# or
if command >/dev/null 2>&1; then
echo "success"
else
echo "fail"
fi
You could also check the variable $? which correspond to the status of the previous command (0 when that command success or another integer value which is 1 in most of cases, or more).

Resources