I am trying to write a small bash script to monitor the output of RiotShield (a 3rd party player scraper for League of Legends) for crashes. If a keyword is found in the log it should kill the process and restart it.
Here is my bash script as is:
#!/bin/bash
crash[1]="disconnected"
crash[2]="38290209"
while true; do
list=$(tail log.log)
#clear
echo "Reading Log"
echo "========================================"
echo $list
for item in ${list//\\n/ }
do
for index in 1 2
do
c=${crash[index]}
#echo "Crash Word:" $c
if [[ "$c" == *"$item"* ]]; then
echo "RiotShield has crashed."
echo "Killing RiotShield."
kill $(ps aux | grep '[R]iotShield.exe' | awk '{print $2}')
echo "RiotShield killed!"
echo "Clearing log."
echo > log.log
echo "Starting RiotShield"
(mono RiotShield.exe >> log.log &)
fi
done
done
sleep 10
done
My crash array are keywords that I know show in the log when it crashes. I have 38290209 in there only for testing purposes as it is my summoner ID on League of Legends and the moment I preform a search for my Summoner name the ID shows in the log.
The problem is even when disconnected and 38290209 do not show up in the log my
if [[ "$c" == *"$item"* ]]; then
fires, kills the RiotShield process and then relaunches it.
The length of the crash array will grow as I find more keywords for crashes so I cant just do
if [[ "$c" == "*disconnected*" ]]; then
Please and thanks SOF
EDIT:
Adding working code:
#!/bin/bash
crash[1]="disconnected"
crash[2]="error"
while true; do
list=$(tail log.log)
clear
echo "Reading Log"
echo "========================================"
echo $list
for index in 1 2
do
c=${crash[index]}
#echo "Crash Word:" $c
if [[ $list == *$c* ]]; then
echo "RiotShield has crashed."
echo "Crash Flag: " $c
echo "Killing RiotShield."
kill $(ps aux | grep '[R]iotShield.exe' | awk '{print $2}')
echo "RiotShield killed!"
echo "Clearing log."
echo > log.log
echo "Starting RiotShield"
(mono RiotShield.exe >> log.log &)
fi
done
sleep 10
done
I think you have the operands in your expression the wrong way around. It should be:
if [[ $item == *$c* ]]; then
because you want to see if a keyword ($c) is present in the line ($item).
Also, I'm not sure why you need to break the line into items by doing this: ${list//\\n/ }. You can just match the whole line.
Also note that double-quotes are not required within [[.
Related
#!/bin/bash
#variables
option=$1
myfile=~/.bdrecord.txt;
#supported options
opts=("-a" "--test" "-app" "-c" "-v");
argc=("ram ram nov 12 pen | --test" "" "1s|1m|1h" "" "");
flag=0;
for o in ${opts[#]}
do
if [[ $o = ${option} ]];
then
flag=1;
break
fi
done
if [[ ${flag} -ne 1 ]];
then
echo -e "Program aborted!\nSupported commands are like"
for i in ${!opts[#]};
do
echo -e "$i.\t" $0 ${opts[$i]} ${argc[$i]}
done
fi
#defaults
name="Rambo"
nickname="Ram"
bmth=$(date +%h);
bday=$(date +%d);
gift="hat-type"
#new feature, handle --test option along with -a option
if [[ ${option} = "-a" ]];
then
while read -r name nickn month day gift
do
if [[ ${2} = ${name} ]];
then
isRepeated=1;
break;
fi
done
if [[ isRepeated == 1 ]]
then
echo "${name} is a repeated name. Try again."
exit 22;
fi
if [[ ${2} = "--test" ]];
then
#add some test data and exit.
for ((i=0;i<5; i++))
do
row="${name}-$i,${nickname},${bmth},$(($bday+$i)),${gift}-${i}";
echo ${row} >> ${myfile}
done
echo "Saved 5 samples in ${myfile}";
echo "...";
tail -n 5 ${myfile};
echo -e ".." $(cat ${myfile} | wc -l) "entries"
exit 0;
fi
#handle more or less than 5 inputs
if [[ $# -ne 6 ]];
then
echo "Expected 5 args (name nickname month day gift) with -a option."
exit 22;
fi
echo "option -a is received!"
#save last 5 inputs in the file
##collect last 5 inputs
name=$2
nickname=$3
bmth=$4
bday=$5
gift=$6
row="${name},${nickname},${bmth},${bday},${gift}";
echo ${row} >> ${myfile}
#display current date
echo "Today: $(date)";
#display "yeah.."
echo "Yeah ${nickname} has been added!"
#display count of records
echo "--------"
wc -l ${myfile}
fi
#handle -c option
#handle -v option
#new feature, handle -app option
if [[ ${option} = "--app" ]];
then
if [[ $# -ne 2 ]];
then
echo "Expected arg sleep time {1s, 2s, 3s..1m, 2m, 3m, ..1h, 2h, 3h..}";
exit 44;
fi
echo "Entered App Mode. Use kill command to kill it."
#find person whose birthday is today
thismonth=$(date +"%h")
ithismonth=$(date +"%m")
thisday=$(date +"%d")
bdlist=();
while IFS="," read -r name nickn month day gift
do
if [[ ("${month,,}" = "${thismonth,,}" \
||
"${month,,}" -eq "${ithismonth,,}") ]] \
&& [[ ${day} = ${thisday} ]]
then
#add to list
bdlist+=("Today is ${name}'s $day birthday! Selected gift is:${gift} ")
fi
done < ${myfile}
while :
do
#every hour send three messages notifying whose birthday is today.
sleep ${2};
for l in "${bdlist[#]}";
do
echo "$l" >> ~/.bdlog.txt;
done
let i++;
done
fi
The instructions of my assignment clearly state to: Modify the given script so that for the "-a" option, the script stores the arguments (name, nickname, birthday month, birthday day, gift) in the file ~/.bdrecord.txt only if the given input name does not exist in the record file ~/.bdrecord.txt
However, my code is erroring. The part that I added is the part where isRepeated is.
I'm trying to do a script that does things on my linux computer but does not respects wait commands.
That's my code that does not work
cat file.txt | while read line || [[ -n $line ]]; do
do
QUEST="$(./fi $line | grep -oE " fi " &> A.txt; echo $? >"$dir")" & proc=$!
wait "$proc"
read ret <"$dir"
if [[ "$QUEST" != "" ]];then echo "$line" &>> A.txt; fi; unset QUEST;
done &> /dev/null & wait
It have to do one quest a time and save the output (that could exists or not).
When you run a command in the background, it's run in a subshell. Any variable assignments are not visible in the original shell, so the assignment to QUEST doesn't work.
You don't need to do that in the background, since you're immediately waiting for the command to finish. Just run it normally.
while read line || [[ -n $line ]]; do
do
QUEST="$(./fi $line | grep -oE " fi " &> A.txt)"
ret=$?
if [[ "$QUEST" != "" ]]
then echo "$line" &>> A.txt
fi
done &> /dev/null < file.txt
unset QUEST
There's also no need to write $? to $dir. The exit status of a variable assignment from a command substitution is the exit status of the command.
So I have this BASH script and what i want to do is, reach out to the servers. Check the used % of a directory. If it is higher than my set threshold (90) then print that server name to another file on the server where the script has been run from.
What it is doing is printing the first server name twice in to the file so it looks like
server1
server2
Here is my script ... I don't see why it would be going around in a loop to that first server twice
#!/bin/bash
SERVERS="server1
server2"
for i in $SERVERS; do
ssh $SERVERS "
df -h | grep var | awk '{print \$4}' | sed 's/%//g' > /home/user/space.txt
RESULTS=\$(grep -E "1[5-9]" /home/user/space.txt)
THRESHOLD=90
if [[ \$RESULTS -lt \$THRESHOLD ]]; then
exit 1;
elif [[ \$RESULTS -gt \$THRESHOLD ]]; then
hostname;
fi
" >> /home/user/problem.txt
done
Try this,
#!/bin/bash
SERVERS="server1
server2"
for i in $SERVERS; do
ssh "$i" "
df -h | grep var | awk '{print \$4}' | sed 's/%//g' > /home/user/space.txt
RESULTS=\$(grep -E "1[5-9]" /home/user/space.txt)
THRESHOLD=90
if [[ \$RESULTS -lt \$THRESHOLD ]]; then
exit 1;
elif [[ \$RESULTS -gt \$THRESHOLD ]]; then
hostname;
fi
" >> /home/user/problem.txt
done
can someone guide me writing shell script to find if the process is active or not? I have to exclude my own grep process filtering from ps command. I want to pass the process as a parameter,
script: (this is currently catching my own process)
#!/bin/sh
SERVICE=$1
echo $1
if ps ax | grep $SERVICE > /dev/null
then
echo "ok"
else
echo "not ok"
fi
example input tried: (though the process is dead I'm getting status as "ok")
./processchecker.sh '/usr/sbin/mysqld'
./processchecker.sh '[/usr/sbin/]mysqld' (i tried using square brackets using online suggestions but failed)
Please help.
You can use pgrep as well - which is a little more efficient:
#!/bin/sh
service=$1
status=0
if [ ! -z "$service" ]; then
pgrep "$service" >/dev/null; status=$?
if [ "$status" -eq 0 ]; then
echo "ok"
else
echo "not ok"
fi
fi
exit "$status"
It's better to have an appropriate exit value as well.
What you have is close, but you want to save the status of the grep command (via $?) and then if/else off of that value.
#!/bin/sh
SERVICE=$1
echo $1
ps ax | grep $SERVICE | grep -v ${0} > /dev/null
status=${?}
if [ "${status}" = "0" ]; then
echo "ok"
else
echo "not ok"
fi
If i wanted to validate a null return from a user keyboard input if the user hasn't selected an option to reprint the menu how could this be achieved? and if a invalid choice is made to clear the screen / reprint the menu but insure the error message is still visible? maybe capture a return code as part of the exit and based on that provide an error?
The file ALIAS_FILE.config consists of these values:
ALIAS1 CLUSTER1
ALIAS2 CLUSTER2
ALIAS3 CLUSTER3
QUIT
Script:
mapfile -t arr < "/var/ALIAS_FILE.config"
select alias_select in "${arr[#]}"
do
if [[ -z "$alias_select" ]]
then
echo
echo "Invalid Choice"
echo
elif [[ $alias_select == "QUIT" ]]
then
break
else
echo
echo "You selected: $alias_select"
echo
ALIAS=$(echo "${alias_select}" | awk '{print $1}')
CLUSTER=$(echo "${alias_select}" | awk '{print $2}')
echo "$ALIAS"
echo "$CLUSTER"
fi
done
As long as you have your file (/var/ALIAS_FILE.config), you should be able to show the menu anytime, you also have access to the values in arr through mapfile here is a quick attempt, with some advices:
use echo -e or event better (and recommended) printf
clear screen, you can use VT100 escape code printf "\033c"
use bash string manipulation
updated script:
#!/bin/bash
mapfile -t arr< "/var/ALIAS_FILE.config"
print_menu(){
for (( i=0; i<${#arr[#]}; i++ ));
do
echo $i")" ${arr[$i]}
done
}
printf "\033c"
select alias_select in "${arr[#]}"
do
printf "\033c"
if [[ -z "$alias_select" ]]
then
echo -e "\nInvalid Choice\n"
print_menu
elif [[ $alias_select == "QUIT" ]]
then
break
else
echo -e "\nYou selected: $alias_select\n"
echo -e "${alias_select// *}\n${alias_select##* }"
fi
done