Bash Script If else statement not capturing the threshold - linux

I am currently attempting to capture the threshold in my script, but it's reading as everything is "above the threshold".
I know that the directory is at 48G and I set the threshold to 99G, expecting "Not above threshold" to appear after running the script. Please advise and see script below for reference...
#!/bin/bash
threshold=99
if [ "du -sh /data | cut -f1 | grep -Eo [0-9]+ -gt $threshold" ]
then
echo "Reducing file with a further commands. File is above the threshold..."
else
echo "Not above threshold..."
fi

You want:
if [ "$(du -sh /data | cut -f1 | grep -Eo '[0-9]+')" -gt "$threshold" ]
Double quotes create a literal string, you need to use $(command) to substitute the output of a command into the command line.

Using --threshold option
value=99
THRESHOLD=$(du -sh --threshold="${value}"G /data)
if [ -n "$THRESHOLD" ]
then
echo "Reducing file with a further commands. File is above the threshold..."
else
echo "Not above threshold..."
fi

Related

Variable comparison in bash

I am trying to find out whether disk is SSD or HDD using bash script.
logical_name="/dev/sda"
type=""
disk=$(basename $logical_name)
x=`cat $filename | grep "${disk}" | awk '{print $2}'`
if [ ! -z "$x" ]
then
if [ "$x" = "0" ]
then
type="SSD"
fi
if [ "$x" = "1" ]
then
type="HDD"
fi
fi
echo $type
Value of x is correct, 0 or 1. But after comparison, it's not assigning any value to variable type. It prints as empty. Can anyone point out what am I doing wrong here?
More information:
$filename is a file that contains output of sudo lsblk -d -o name,rota
NAME ROTA
sda 1
sdd 1
sdc 0
While I don't see any problem with the posted code, following would be a more simplified and maintainable version for doing the same.
DISK_NAMES=(SSD HDD) # names are resolved by index
filename="in1.txt"
logical_name="/dev/sda"
disk="$(basename $logical_name)"
x="$(sed -n 's/'$disk' *\([0-9]*\)/\1/p' $filename)"
# check if $x is empty here, if required
echo "$x -> ${DISK_NAMES[$x]}"
The lsblk command lets you specify a device, so you shouldn't have to grep through the lsblk output to find the device you're interested in. This also means you don't need the name column. Plus you can disable the header with -n, and the -r option (raw output) gets rid of the leading and trailing whitespace:
> hdtype() { lsblk -drno rota "$1" | sed 's/1/HDD/;s/0/SSD/'; }
> hdtype /dev/sda
HDD
As far as why your code isn't working, I'm not sure. It worked just fine in my bash terminal.

shell script error when declaring command

Code below is supposed to check the memory for user and if its greater than 1000, print message
I keep getting error- line 4: impala: command not found
#!/bin/bash
while [ true ] ;do
used= `ps hax -o rss,user | awk '{a[$2]+=$1;}END{for(i in a)print i"
"int(a[i]/1024+0.5);}' | grep user`
if [[ $used > 1000 ]]; then
echo "user memory is $used"
fi
sleep 5
done
I have tried used= ps hax -o rss,user | awk '{a[$2]+=$1;}END{for(i in a)print i" "int(a[i]/1024+0.5);} | grep user'
and used= 'ps hax -o rss,user | awk '{a[$2]+=$1;}END{for(i in a)print i" "int(a[i]/1024+0.5);}' | grep user'
I need a fresh eye on this. Please help.
In bash, as mentioned [ here ], putting spaces around the equal sign would cause errors, So the right format is
variable_name=value;
Moreover, you may change
while [ true ]
to
while true
Edit
If used has the form impala 600 and you're only interested in the number at the end, then you may do
used="${used##* }"
#Do this just after the your first command.
Finally do
#use -gt for integer comparisons and > for string comparisons
if ! [ -t $used ] && [ $used -gt 1000 ]
then
echo "user memory is $used"
fi
Note: Though the syntax errors in the script is resolved there is no guarantee that the program logic is right

sed is not working for commenting a line in a file using bash script

I have created a bash script that is used to modify the ulimit of open files in the RHEL server.
so i have reading the lines in the file /etc/security/limits.conf and if the soft/hard limit of the open files are less than 10000 for '*' domain i am commenting the line and adding a new line with soft/hard limit as 10000.
The Script is working as designed but the sed command to comment a line in the script is not working.
Please find the full script below :-
#!/bin/sh
#This script would be called by '' to set ulimit values for open files in unix servers.
#
configfile=/etc/security/limits.conf
help(){
echo "usage: $0 <LimitValue>"
echo -e "where\t--LimitValue= No of files you want all the users to open"
exit 1
}
modifyulimit()
{
grep '*\s*hard\s*nofile\s*' $configfile | while read -r line ; do
firstChar="$(echo $line | xargs | cut -c1-1)"
if [ "$firstChar" != "#" ];then
hardValue="$(echo $line | rev | cut -d ' ' -f1 | rev)"
if [[ "$hardValue" -ge "$1" ]]; then
echo ""
else
sed -i -e 's/$line/#$line/g' $configfile
echo "* hard nofile $1" >> $configfile
fi
else
echo ""
fi
done
grep '*\s*soft\s*nofile\s*' $configfile | while read -r line ; do
firstChar="$(echo $line | xargs | cut -c1-1)"
if [ "$firstChar" != "#" ];then
hardValue="$(echo $line | rev | cut -d ' ' -f1 | rev)"
if [[ "$hardValue" -ge "$1" ]]; then
echo ""
else
sed -i -e 's/$line/#$line/g' $configfile
echo "* hard nofile $1" >> $configfile
fi
else
echo ""
fi
done
}
deleteEofTag(){
sed -i "/\b\(End of file\)\b/d" $configfile
}
addEofTag()
{
echo "#################End of file###################" >> $configfile
}
#-------------Execution of the script starts here ----------------------
if [ $# -ne 1 ];
then
help
else
modifyulimit $1
deleteEofTag
addEofTag
fi
The command sed -i -e 's/$line/#$line/g' $configfile when executed from the terminal is working absolutely fine and it is commenting the line but it is not working when i am executing it from the unix shell script.
interpolation does not work in single quote
use double quote and try
sed -i -e 's/$line/#$line/g'
sed -i -e "s/$line/#$line/g"
also you might try:
sed -i -e s/${line}/#${line}/g
as this will tell the script to take the value of the variable instead of variable as such.

Why do this sample script, keep outputting error near token?

enter image description hereI was trying to see how a shell scripts work and how to run them, so I toke some sample code from a book I picked up from the library called "Wicked Cool Shell Scripts"
I re wrote the code verbatim, but I'm getting an error from Linux, which I compiled the code on saying:
'd.sh: line 3: syntax error near unexpected token `{
'd.sh: line 3:`gmk() {
Before this I had the curly bracket on the newline but I was still getting :
'd.sh: line 3: syntax error near unexpected token
'd.sh: line 3:`gmk()
#!/bin/sh
#format directory- outputs a formatted directory listing
gmk()
{
#Give input in Kb, output converted to Kb, Mb, or Gb for best output format
if [$1 -ge 1000000]; then
echo "$(scriptbc -p 2 $1/1000000)Gb"
elif [$1 - ge 1000]; then
echo "$$(scriptbc -p 2 $1/1000)Mb"
else
echo "${1}Kb"
fi
}
if [$# -gt 1] ; then
echo "Usage: $0 [dirname]" >&2; exit 1
elif [$# -eq 1] ; then
cd "$#"
fi
for file in *
do
if [-d "$file"] ; then
size = $(ls "$file"|wc -l|sed 's/[^[:digit:]]//g')
elif [$size -eq 1] ; then
echo "$file ($size entry)|"
else
echo "$file ($size entries)|"
fi
else
size ="$(ls -sk "$file" | awk '{print $1}')"
echo "$file ($(gmk $size))|"
fi
done | \
sed 's/ /^^^/g' |\
xargs -n 2 |\
sed 's/\^\^\^/ /g' | \
awk -F\| '{ printf "%39s %-39s\n", $1, $2}'
exit 0
if [$#-gt 1]; then
echo "Usage :$0 [dirname]" >&2; exit 1
elif [$# -eq 1]; then
cd "$#"
fi
for file in *
do
if [ -d "$file" ] ; then
size =$(ls "$file" | wc -l | sed 's/[^[:digit:]]//g')
if [ $size -eq 1 ] ; then
echo "$file ($size entry)|"
else
echo "$file ($size entries)|"
fi
else
size ="$(ls -sk "$file" | awk '{print $1}')"
echo "$file ($(convert $size))|"
fi
done | \
sed 's/ /^^^/g' | \
xargs -n 2 | \
sed 's/\^\^\^/ /g' | \
awk -F\| '{ printf "%-39s %-39s\n", $1, $2 }'
exit 0
sh is very sensitive to spaces. In particular assignment (no spaces around =) and testing (must have spaces inside the [ ]).
This version runs, although fails on my machine due to the lack of scriptbc.
You put an elsif in a spot where it was supposed to be if.
Be careful of column alignment between starts and ends. If you mismatch them it will easily lead you astray in thinking about how this works.
Also, adding a set -x near the top of a script is a very good way of debugging what it is doing - it will cause the interpreter to output each line it is about to run before it does.
#!/bin/sh
#format directory- outputs a formatted directory listing
gmk()
{
#Give input in Kb, output converted to Kb, Mb, or Gb for best output format
if [ $1 -ge 1000000 ]; then
echo "$(scriptbc -p 2 $1/1000000)Gb"
elif [ $1 -ge 1000 ]; then
echo "$(scriptbc -p 2 $1/1000)Mb"
else
echo "${1}Kb"
fi
}
if [ $# -gt 1 ] ; then
echo "Usage: $0 [dirname]" >&2; exit 1
elif [ $# -eq 1 ] ; then
cd "$#"
fi
for file in *
do
if [ -d "$file" ] ; then
size=$(ls "$file"|wc -l|sed 's/[^[:digit:]]//g')
if [ $size -eq 1 ] ; then
echo "$file ($size entry)|"
else
echo "$file ($size entries)|"
fi
else
size="$(ls -sk "$file" | awk '{print $1}')"
echo "$file ($(gmk $size))|"
fi
done | \
sed 's/ /^^^/g' |\
xargs -n 2 |\
sed 's/\^\^\^/ /g' | \
awk -F\| '{ printf "%39s %-39s\n", $1, $2}'
exit 0
By the way, with respect to the book telling you to modify your PATH variable, that's really a bad idea, depending on what exactly it advised you to do. Just to be clear, never add your current directory to the PATH variable unless you intend on making that directory a permanent location for all of your scripts etc. If you are making this a permanent location for your scripts, make sure you add the location to the END of your PATH variable, not the beginning, otherwise you are creating a major security problem.
Linux and Unix do not add your current location, commonly called your PWD, or present working directory, to the path because someone could create a script called 'ls', for example, which could run something malicious instead of the actual 'ls' command. The proper way to execute something in your PWD, is to prepend it with './' (e.g. ./my_new_script.sh). This basically indicates that you really do want to run something from your PWD. Think of it as telling the shell "right here". The '.' actually represents your current directory, in other words "here".

No such file or directory error while execute commands from script

I'm working on a script that takes commands from MySQL and executes them one by one. My problem is I can't execute the commands from script:
./bash.sh: line 26: /myscript.sh -c "": no such file or directory
Line 26 is the command I wish to execute ("$com"). if i try to run the command manually, by echoing the content of "$com" and than run it from terminal, it's working.
What am I doing wrong?
if [ ! "${#array[*]}" -eq "0" ]; then
for (( i=0 ; i<cnt ; i++ )); do
id=$(echo "${array[$i]}" | sed 's#\t#^#g' | cut -f'1' -d'^')
com=$(echo "${array[$i]}" | sed 's#\t#^#g' | cut -f'2' -d'^')
imp=$(echo "${array[$i]}" | sed 's#\t#^#g' | cut -f'3' -d'^')
if [[ "$id" = [0-9]* ]]; then
"$com"
echo "DELETE FROM list WHERE id='$id'" | mysql "$DB_USER" -u "$DB_USER" -p"$DB_PASS"
fi
done
else
echo "The list is empty"
fi
Added as Community Wiki
This question was solved in the comments by Vaughn Cato and the OP hasn't been seen since March.
The accept answer there was to use eval so the if statement in the script would be:
if [[ "$id" = [0-9]* ]]; then
eval "$com"
echo "DELETE FROM list WHERE id='$id'" | mysql "$DB_USER" -u "$DB_USER" -p"$DB_PASS"
fi
Change
"$com"
rather to
$com
(remember: too many quotes can be as harmful as too few)
than to
eval "$com"
it is unnecessarily complicated to use eval just to undo the unwanted effect of quoting.

Resources