I have a script which utilises SaltStack's command-line as well as BASH commands. The script is used to gather data from multiple Linux servers (hence SaltStack), one of the checks which I would like to gather is disk space.
I have done this by using the following command:
salt $i cmd.run 'df -Ph / | tail -n1 | awk '"'"'{ print $4}'"'"'' | grep -v $i
$i = hostname and the use of the ugly '"'"' is so that my command can run via SaltStack as Salt's remote execution functionality requires single quotes around the command, if I left them in my command wouldn't run inside my BASH script.
Example syntax:
salt $hostname cmd.run 'command here'
After many questions on here and with colleagues I have this section of the script sorted. However I now the problem of stripping the output of my above command to remove the 'G' so that my script can compare the output with a threshold I have defined and turn the HTML which this script is piping to red.
Threshold:
diskspace_threshold=5
Command:
while read i ; do
diskspace=`salt $i cmd.run 'df -Ph / | tail -n1 | awk '"'"'{ print $4}'"'"'' | grep -v $i`
Validation check:
if [[ "${diskspace//G}" -lt $diskspace_threshold ]]; then
ckbgc="red"
fi
The method I have used for stripping the G works on the command line but not within my script so it must be something to do with the syntax or just the fact that it is now within a script. Any ideas/thoughts would be helpful.
Cheers!
EDIT: Here is the error message I receive when running my script:
serverdetails.sh: line 36: p
: 2.8: syntax error: invalid arithmetic operator (error token is ".8")
I assume the error is coming from here (is this line 36?)
if [[ "${diskspace//G}" -lt $diskspace_threshold ]]; then
Note the error message:
serverdetails.sh: line 36: p : 2.8: syntax error: invalid arithmetic operator (error token is ".8")
bash does not do floating point arithmetic
$ [[ 2.8 -lt 3 ]] && echo OK
bash: [[: 2.8: syntax error: invalid arithmetic operator (error token is ".8")
You'll need to do something like this:
result=$( bc <<< "${diskspace%G} < $diskspace_threshold" )
if [[ $result == 1 ]]; then
echo OK
else
echo Boo
fi
Related
I'm writing a script to run another script with parameters and store the output into a variable.
The output has multiple lines but I only need one single line containing one of four specific strings and do something based on which string was found.
I want to store the output from the command into $OUTPUT but unable to parse and get the required lines to run an additional script.
OUTPUT="$(script.php $HOST $PARAMETER)"
Tried a simple if statement below but i'm already failing with:
RESULT=$(grep "TEST" $OUTPUT)
if [ $? -eq 0 ]; then
printf '%s\n' "$RESULT"
else
printf '%s\n' "No Match"
fi
This is what I'm getting, where '-p' is the $PARAMETER when executing the script:
grep: invalid option -- 'p'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
Where I'm getting the correct output with:
printf '%s\n' "$OUTPUT"
The problem is, that value of $OUTPUT are interpreted as shell command line parameters in this line:
RESULT=$(grep "TEST" $OUTPUT)
try:
RESULT=$(echo "$OUTPUT" | grep "TEST")
The simplest way to avoid this error and do not thread strings like -p as parameters is to rewrite your grep line like this:
RESULT=$(grep -- "TEST" $OUTPUT)
Double dash tell grep this is the end of parameter and all the rest is threaded as data
I have the following script called test.sh:
echo "file path is : $1"
path=$1
while read -r line
do
num=$($line | tr -cd [:digit:])
echo num
done < $path
exit 0
I am attempting to grab the digit at the start of each line of the file stored as $path. the end result will be to loop over each line, grab the digit and remove it from the file if it is less than 2.
Every time i run this loop i get the error "./test.sh: line 5: : command not found. What part of the while loop am I doing wrong? Or is it something to do with the tr command?
I can spot a few things wrong with your script:
#!/bin/bash
echo "file path is : $1"
path=$1
while read -r line
do
num=$(tr -cd '[:digit:]' <<<"$line") # use here string to "echo" variable to tr
echo "$num" # added quotes and $
done < "$path" # added quotes, changed $dest to $path
In summary:
cmd <<<"$var" (here string) is a bash built-in designed as a replacement for echo "$var" | cmd. I added #!/bin/bash to the top of the script, as I am using this bash-only feature.
I have quoted your variables to prevent problems with word splitting and glob expansion.
I made the assumption that you really meant to use $path on the last line (though I may be wrong).
Finally, there's no need to exit 0 at the end of your script.
I have written the following shell script
while :; do
status=$($EMR_BIN/elastic-mapreduce --jobflow $JOBFLOW --list | grep "CopyLogs" | awk '{print $1}')
[[ $status == +( *RUNNING*|*PENDING*|*WAITING* ) ]] || break
sleep 60
done
Its giving me an error in line 3 saying syntax error in conditional expression: unexpected token('' . I tried giving whitespaces between my braces, but its not working.
Can anyone help me out.
Looks like you are trying to use extended globbing. Make sure you have shopt -s extglob somewhere earlier in your script, or rewrite to use standard globbing.
#!/bin/sh
while :; do
case $($EMR_BIN/elastic-mapreduce --jobflow $JOBFLOW --list | awk '/CopyLogs/{print $1}') in
*RUNNING*|*PENDING*|*WAITING* ) sleep 60;;
*) break;;
esac
done
Since there are no remaining Bashisms, this script is now POSIX sh compatible. (Personally, I also think it is more readable this way.)
(Note also the fix for the useless grep | awk.)
Shell script snippet:
tagSearch= $(grep '^\#ctags$' ./"$1" | wc -l)
if [[ $tagSearch -ne "0" ]]
then
...
fi
Results in:
line 2: /bb/bin/1: Permission denied
Context:
I'm trying to detect whether a particular pattern exists in a file so I can take a particular action.
I understand the error I'm getting, the detection is working but the script is trying to evaluate the result '1' and run the program '1' in my path. This isn't what I want. How do I get the behavior I'm looking for?
The problem is
tagSearch= $(grep '^\#ctags$' ./"$1" | wc -l)
----------^
You can't use spaces around the equal sign; what you're actually doing here is to temporarily set tagSearch to the empty string in the environment, then invoking grep '^\#ctags$' ./"$1" | wc -l, then trying to run that as a command since the $() will have inserted the result into the command line.
tagSearch=$(grep '^\#ctags$' ./"$1" | wc -l)
Variable assignments in the bash shell should not have a space after the equals. Actually it should never have whitespace in it at all. See below.
tagSearch=$(grep '^\#ctags$' "./$1" | wc -l)
if [[ $tagSearch -ne 0 ]]
then
...
fi
Not important to your error but also of note, when using the double bracket syntax, you don't need to quote that zero any more than the variable you are comparing it with.
Actually your whole code could be re-factored using grep's quite mode and evaluating the return code to see if you got any matches:
if grep '^\#ctags$' "./$1"
then
...
fi
Actually you can have that simpler, because the return code of grep will be 0 if something is found (1 otherwise), so you don't need wc -l. And you can just write:
if `grep -q pattern file`; then echo "yes"; else echo "no"; fi;
the following script is working fine on one server but on the other it gives an error
#!/bin/bash
processLine(){
line="$#" # get the complete first line which is the complete script path
name_of_file=$(basename "$line" ".php") # seperate from the path the name of file excluding extension
ps aux | grep -v grep | grep -q "$line" || ( nohup php -f "$line" > /var/log/iphorex/$name_of_file.log & )
}
FILE=""
if [ "$1" == "" ]; then
FILE="/var/www/iphorex/live/infi_script.txt"
else
FILE="$1"
# make sure file exist and readable
if [ ! -f $FILE ]; then
echo "$FILE : does not exists. Script will terminate now."
exit 1
elif [ ! -r $FILE ]; then
echo "$FILE: can not be read. Script will terminate now."
exit 2
fi
fi
# read $FILE using the file descriptors
# $ifs is a shell variable. Varies from version to version. known as internal file seperator.
# Set loop separator to end of line
BACKUPIFS=$IFS
#use a temp. variable such that $ifs can be restored later.
IFS=$(echo -en "\n")
exec 3<&0
exec 0<"$FILE"
while read -r line
do
# use $line variable to process line in processLine() function
processLine $line
done
exec 0<&3
# restore $IFS which was used to determine what the field separators are
IFS=$BAKCUPIFS
exit 0
i am just trying to read a file containing path of various scripts and then checking whether those scripts are already running and if not running them. The file /var/www/iphorex/live/infi_script.txt is definitely present. I get the following error on my amazon server-
[: 24: unexpected operator
infinity.sh: 32: cannot open : No such file
Thanks for your helps in advance.
You should just initialize file with
FILE=${1:-/var/www/iphorex/live/infi_script.txt}
and then skip the existence check. If the file
does not exist or is not readable, the exec 0< will
fail with a reasonable error message (there's no point
in you trying to guess what the error message will be,
just let the shell report the error.)
I think the problem is that the shell on the failing server
does not like "==" in the equality test. (Many implementations
of test only accept one '=', but I thought even older bash
had a builtin that accepted two '==' so I might be way off base.)
I would simply eliminate your lines from FILE="" down to
the end of the existence check and replace them with the
assignment above, letting the shell's standard default
mechanism work for you.
Note that if you do eliminate the existence check, you'll want
to either add
set -e
near the top of the script, or add a check on the exec:
exec 0<"$FILE" || exit 1
so that the script does not continue if the file is not usable.
For bash (and ksh and others), you want [[ "$x" == "$y" ]] with double brackets. That uses the built-in expression handling. A single bracket calls out to the test executable which is probably barfing on the ==.
Also, you can use [[ -z "$x" ]] to test for zero-length strings, instead of comparing to the empty string. See "CONDITIONAL EXPRESSIONS" in your bash manual.