How to grep success in a for loop - loops

Struggling with this...
for i in `cat services.txt`
do
if ! grep -q $i; then
echo " $i Is NOT Running"
else
echo " Checking $i on `hostname`..."
ps aux | grep -i $i | awk '{print $1, $11}'| cut -d' ' -f1-2| sort
echo -e " "
sleep 4
fi
done
The block just hangs - Ive not been able to capture the success/failure of grep
If a string in services.txt is NOT found ... the script hangs... Id like for grep to skip it if not found
services.txt contain just single words
thanks!

The reason your script hangs is beacuse the command grep -q $i is waiting for an input. You can try running that command separately in a shell and verify that it prompts for an input.
Changing your command to ps aux | grep -i $i in the if statement should fix your issue.
NOTE: ps aux | grep -i $i lists grep also as one of the process. Make sure you exclude that process by piping it to another grep ps aux | grep -i $i | grep -v 'grep'

here is the working code
checkservices() {
cat >$HOME/services.txt <<EOF
ganglia
hbase
hdfs
hive
hue
livy
mapred
test-missing-service
mysql
oozie
presto
spark
yarn
zeppelin
EOF
for i in `cat $HOME/services.txt`
do
if `ps -ef | grep ^$i | grep -v grep >/dev/null`
then
i=$(echo "$i" | awk '{print toupper($0)}')
echo "$i -- is running on `hostname`"
echo ""
sleep 2
else
i=$(echo "$i" | awk '{print tolower($0)}')
echo "$i -- IS NOT running on `hostname` error"
echo ""
fi
done
}

Related

Echo 2 Arrays Lists in Shell Script

I have a problem with array in bash. I wish to echo 2 Arrays in a list from the fist element from the convert array til the last element. The same thing for room_minute array.
#! /bin/bash
#! /usr/bin/perl
declare -a data;
declare -a convert;
declare -a sala_minutos;
data=($(./Minutes.php 2> /dev/null | grep -P -w -o [0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\} | awk -v FS=/ -v OFS=/ '{print $2,$1,$3}'));
room_minutes=($(./Minutes.php 2> /dev/null | grep -oP '(?<=room: )[0-9]+'))
for ((i=0; i< ${#data[*]}; i++));
do
convert=($(date -d "${data[i]} 10:00:00" +%s));
done
echo ${convert[*]} ${room_minutes[*]}
Obs inside the arrays:
data = [09/03/16 09/01/16 09/02/16 09/03/16 09/04/16 09/05/16 09/06/16 09/07/16 09/08/16 09/09/16 09/10/16 09/11/16 09/12/16 09/13/16 08/25/16 08/26/16 08/27/16 08/28/16 08/29/16 08/30/16 08/31/16]
covert = [1472698800 1472785200 1472871600 1472958000 1473044400 1473130800 1473217200 1473303600 1473390000 1473476400 1473562800 1473649200 1473735600 1472094000 1472180400 1472266800 1472353200 1472439600 1472526000 1472612400]
room_minutes = [7339 8748 211 15 15927 7028 34 11112 12567 686 5 13988 11279 8465 4402 60 1 10380 8078 8422]
Thanks in Advance.
i think you want convert and room_minutes in two columns. i've changed as little as possible to accomplish this using multiline strings and paste instead of arrays. the data= and room_minutes= lines are unchanged except for stripping the outermost ()s.
#!/bin/bash
data=$(./Minutes.php 2> /dev/null | grep -P -w -o [0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\} | awk -v FS=/ -v OFS=/ '{print $2,$1,$3}');
room_minutes=$(./Minutes.php 2> /dev/null | grep -oP '(?<=room: )[0-9]+');
convert=$(echo "$data" | xargs -I{} date -d "{} 10:00:00" +%s)
paste <(echo "$convert") <(echo "$room_minutes")
#!/bin/bash
data=($(./Minutes.php 2> /dev/null | grep -P -w -o [0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\} | awk -v FS=/ -v OFS=/ '{print $2,$1,$3}'));
room_minutes=($(./Minutes.php 2> /dev/null | grep -oP '(?<=room: )[0-9]+'));
for ((i=0; i< ${#data[#]}; i++));
do
convert=($(date -d "${data[$i]} 10:00:00" +%s));
echo -e Room_Minutes ${convert[#]} ${room_minutes[$i]}
done

How to split input string into multiple variable

I'm working on shell script and trying to split user input into multiple variable and use them at different places.
User input is not fixed so can't really assign fixed number of variable, input is separated by comma ,
./user_input.ksh -string /m01,/m02,/m03
#!/bin/ksh
STR=$2
function showMounts {
echo "$STR"
arr=($(tr ',' ' ' <<< "$STR"))
printf "%s\n" "$(arr[#]}"
for x in "$(arr[#]}"
do
free_space=`df -h "$x" | grep -v "Avail" | awk '{print $4}'`
echo "$x": free_space "$free_space"
done
#total_free_space = <total of $free_space>
#echo "$total_free_space"
}
Basically $STR* variable value is filesystem mount points
Host output if run separate df -h command
$ df -h /m01 | grep -v "Avail" | awk '{print $4}'
***Output***
150
Current problems:
(working)1. How to get free space available for each /m* using df -h?
Easiest thing to do is to use shell array here like this:
#!/bin/ksh
str='/m01,/m02,/m03'
arr=($(tr ',' ' ' <<< "$str"))
printf "%s\n" "${arr[#]}"
Output:
/m01
/m02
/m03
To read elements individually you can use:
"${arr[0]}"
"${arr[1]}"
...
Update: Here is your corrected script:
#!/bin/ksh
STR="$2"
arr=($(tr ',' ' ' <<< "$STR"))
printf "<%s>\n" "${arr[#]}"
for x in "${arr[#]}"; do
echo "$x"
free_space=`df -h "$x" | awk '!/Avail/{print $4}'`
echo "$free_space"
done
you can try,
#!/bin/ksh
STR=/m01,/m02,/m03
read STR1 STR2 STR3 <<<`echo $STR | awk 'BEGIN{FS=","; OFS=" "}{$1=$1; print}'`
echo $STR1 - $STR2 - $STR3
you get:
/m01 - /m02 - /m03
A variation on the theme:
# cat user_input.ksh
#!/bin/ksh
c=1
for i in $(echo ${#} | tr "," " ")
do
eval STR$c="$i"
((c=c+1))
done
printf "\$STR1 = %s; \$STR2 = %s; \$STR3 = %s; ...\n" "$STR1" "$STR2" "$STR3"
Which gives you:
# ksh ./user_input.ksh /m01,/m02,/m03,/m04
$STR1 = /m01; $STR2 = /m02; $STR3 = /m03; ...
Hope that helps..
--ab1
$ cat tst.sh
str='/m01,/m02,/m03'
IFS=,
set -- $str
for i
do
echo "$i"
done
$ ./tst.sh
/m01
/m02
/m03
Don't use all-upper-case for variable names unless you are going to export them (by convention and to avoid clashes with built in names like HOME, PATH, IFS, etc.).
For your overall script, you should simply be doing something like this:
df -h "${str//,/ }" | awk '/^ /{print $5, $3; sum+=$3} END{print sum}'
depending on what your df -h output looks like and what you're final output is supposed to be.

How to deny empty array indexes in bash

I wrote the bash like so:
#!/bin/bash
GAP=1
Out=$1
ResultFile=$2
len=`wc -l $Out | awk '{print $1}'`
eval "(COMMAND) &"
pid=$!
i=0
while kill -0 $pid; do
if [ -N $Out ]; then
newlen=`wc -l $Out | awk '{print $1}'`
newlines=`expr $newlen - $len`
tail -$newlines $Out > temp
IP=( $(sed -n '<SomeThing>' temp) )
host=${IP[$i]}
echo "exit" | nc $host 23
if [ "$?" -eq "0" ]; then
(
<DoingSomeThing>
) | nc $host 23 1>>$ResultFile 2>&1
fi
len=$newlen
let i++
fi
sleep $GAP
done
When the command IP=( $(sed -n '<SomeThing>' temp) ) is running in my bash maybe the result of sed command is nothing and maybe the output is ip. I want only when output of sed command get ip write it into array and when the output of sed is empty does not write it to array.
Thank you
You're not doing your script right in many ways but about your question, the quick way is to store the output first on a variable:
SED_OUT=$(sed -n '<SomeThing>' temp)
[[ -n $SED_OUT ]] && IP=($SED_OUT) ## Would only alter IP if $SED_OUT has a value.

BASH: grep with g=db_$((e ))

i am still writing a bash script and need your help !
I want to grep with two parameters, but it doesn't work.
This script stands in an until queue so it runs x times.
Please help me:
e=1
g=db_$((e++))
for call in $(cat /home/palyground/foo.xml |grep $HOME|grep db_$g| awk -F \" '{print $2}')
do
:
done
echo $call
My Problem is, that the $g is still standing by 1 and dont move to 2 3 eg.
I want to grep |grep db_1 in the first time in the second time |grep db_2 e.g.
Do you have any soulutions for this Problem ?
Try
g=$((++e))
for call in $(awk -F \" '$0~home && $0~db {print $2}' home="$HOME" db="db_$g" /home/palyground/foo.xml)
By changing to ++e it will starts with 1 instead of 0
So i get the right code now..
First time thank you very much Jotne and chepner !
The right code:
f=1
q=/home/playground/foo.xml
g=db_$((f++))
HOME_GREP=${DB_HOME}/${g}
var1=$(cat $q | grep ${HOME_GREP} )
var2=$(echo $var1| awk -F \" '{print $2}' )
echo $var2

Bash: Script for finding files by mime-type

First, I am not experienced in scripting, so be gentle with me
Anyway, I tried making a script for finding files by mime-type ( audio, video, text...etc), and here's the poor result I came up with.
#!/bin/bash
FINDPATH="$1"
FILETYPE="$2"
locate $FINDPATH* | while read FILEPROCESS
do
if file -bi "$FILEPROCESS" | grep -q "$FILETYPE"
then
echo $FILEPROCESS
fi
done
It works, but as you could guess, the performance is not so good.
So, can you guys help me make it better ? and also, I don't want to rely on files extensions.
Update:
Here's what I am using now
#!/bin/bash
FINDPATH="$1"
find "$FINDPATH" -type f | file -i -F "::" -f - | awk -v FILETYPE="$2" -F"::" '$2 ~ FILETYPE { print $1 }'
Forking (exec) is expensive. This runs the file command only once, so it is fast:
find . -print | file -if - | grep "what you want" | awk -F: '{print $1}'
or
locate what.want | file -if -
check man file
-i #print mime types
-f - #read filenames from the stdin
#!/bin/bash
find $1 | file -if- | grep $2 | awk -F: '{print $1}'
#!/usr/bin/env bash
mimetypes=$(sed -E 's/\/.*//g; /^$/d; /^#/d' /etc/mime.types | uniq)
display_help(){
echo "Usage: ${0##*/} [mimetype]"
echo "Available mimetypes:"
echo "$mimetypes"
exit 2
}
[[ $# -lt 1 ]] && display_help
ext=$(sed -E "/^${1}/!d; s/^[^ \t]+[ \t]*//g; /^$/d; s/ /\n/g" /etc/mime.types | sed -Ez 's/\n$//; s/\n/\\|/g; s/(.*)/\.*\\.\\(\1\\)\n/')
find "$PWD" -type f -regex "$ext"

Resources