Want to make a shell script that - linux

Want to make a shell script that runs a program, then if the memory reach over specific limit(example 3gb), it shutdown and restart itself.
While running
If memory > 3gb
Shutdown
Restart

MEM_LIMIT=3145728
MEM_USED=$(cat /proc/meminfo | grep "MemFree" | awk -F' ' '{print $2}' | tr -d " ")
if [ $MEM_USED -ge $MEM_LIMIT ]
then
reboot 0
fi

Related

Multiple PIDs being stored in PID file

I have a System V init script I've developed that starts a Java program. For some reason whenever the PID file gets created, it contains multiple PIDs instead of one.
Here's the relevant code that starts the service and writes to the PID file:
daemon --pidfile=$pidfile "$JAVA_CMD &" >> $logfile 2>&1
RETVAL=$?
usleep 500000
if [ $RETVAL -eq 0 ]; then
touch "$lock"
PID=$(ps aux | grep -vE 'grep|runuser|bash' | grep <myservice> | awk '{print $2}')
echo $PID > $pidfile
When I test the ps aux... command manually, a single line returns. When running as a script, it appears that this call is returning multiple PIDs.
Example contents in the PID file: 16601 16602 16609 16619 16690. 16619 is the actual process ID found when manually running the ps aux... command mentioned above.
Try reversing your greps. The first one (-vE) may run BEFORE the myservice one starts up. Grep for your service FIRST, then filter out the unwanted lines:
PID=$(ps aux | grep <myservice> | grep -vE 'grep|runuser|bash' | awk '{print $2}')
I encounted the same issue but not the same statement, it was like this:
PID="$(ps -ef|grep command|grep options|grep -v grep|awk '{print $2}')"
in which I used the same grep order as #Marc said in first answer, but did not filter all the unwanted lines.
So I tried the below one and it worked:
PID="$(ps -ef|grep command|grep options|grep -vE 'grep|runuser|bash'|awk '{print $2}')"

Bash script kill command in for loop

I want to kill all processes containing some string. I wrote script for doing this. However, when I execute it, it gets "Killed" signal after first iteration of for loop. This is my code:
#!/bin/bash
executeCommand () {
local pname="$1";
echo $HOSTNAME;
local search_terms=($(ps aux | grep $pname | awk '{print $2}'))
for pros in "${search_terms[#]}"; do
kill -9 "$pros"
echo $pros
done
exit
}
executeCommand "$1" # get the string that process to be killed contains
I execute it like ./my_script.sh zookeeper.
When I delete the line containing kill command, for loop executes until end, otherwise, after first kill command, I get as an output "Killed" and program exits.
What is possible reason for this, and any other solution to reach my goal?
The silly (faulty, buggy) way to do this is to add grep -v grep to your pipeline:
# ${0##*/} expands to the name of the running script
# ...thus, we avoid killing either grep, or the script itself
ps aux | grep -e "$pname" | egrep -v "grep|${0##*/}" | awk '{print $2}'
The better way is to use a tool built for the job:
# pkill already, automatically, avoids killing any of its parent processes
pkill "$pname"
That said, matching processes by name is a bad practice to start with -- you'll also kill less yourproc.log or vim yourproc.conf, not just yourproc. Don't do it; instead, use a proper process supervision system (upstart, DJB daemontools, Apple launchd, systemd, etc) to monitor your long-running daemons and kill or restart them when needed.
By the way -- there's no need for a for loop at all: kill can be passed multiple PIDs on a single invocation, like so:
# a bit longer and bash-specific, but avoids globbing
IFS=$'\n' read -r -d '' -a pids \
< <(ps auxw | awk -v proc="$pname" -v preserve="${0##*/}" \
'$0 ~ proc && $0 !~ preserve && ! /awk/ { print $2 }' \
&& printf '\0')
kill -- "${pids[#]}"
...which could also be formulated as something like:
# setting IFS and running `set -f` necessary to make unquoted expansion safe
( IFS=$'\n'; set -f; exec kill -- \
$(ps auxw | awk -v proc="$pname" -v preserve="${0##*/}" \
'$0 ~ proc && $0 !~ preserve && ! /awk/ { print $2 }') )
grep will show , it's own process . it should be removed using grep -v option
Try like this
for i in ` ps -ef | grep "$pname" | grep -v grep | awk '{print $2}'`
do
kill -9 $i
done

Junk characters being printed with tee command

Script I'm utilizing is below:
#!/bin/bash
lla=$(top -n 1 | grep "load average" | awk '{print $13,$14,$15}')
mem_usage=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
now=`date`
cur_time=$(echo $now | awk '{print $4}')
for i in {1..60}
do
echo "System Performance Statistics at: "$cur_time | tee -a hp.txt
echo "Linux Load Average: "$lla | tee -a hp.txt
echo "Memory Usage: "$mem_usage | tee -a hp.txt
echo "" | tee -a hp.txt
sleep 3
done
Results:
System Performance Statistics at: 19:00:29
Linux Load Average: 0.13, 0.11, 0.14^[(B^[[m^[[39;49m^[[K
Memory Usage: 82.7672
Standard out isn't showing any garbage characters at all. What do I need to change?
Added -b to top command and it works.
From man top:
-b :Batch-mode operation
Starts top in Batch mode, which could be useful for sending output
from top to other programs or to a file. In this mode, top will not
accept input and runs until the iterations limit you've set with the
`-n' command-line option or until killed.

Awk not working inside bash script

Im trying to write a bash script and trying to take input from user and executing a kill command to stop a specific tomcat.
...
read user_input
if [ "$user_input" = "2" ]
then
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}| xargs kill -9
echo "Search Tomcat Shut Down"
fi
...
I have confirmed that the line
ps -ef | grep "search-tomcat"
works fine in script but:
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}
doesnt yield any results in script, but gives desired output in terminal, so there has to be some problem with awk command
xargs can be tricky - Try:
kill -9 $(ps -ef | awk '/search-tomcat/ {print $2}')
If you prefer using xargs then check man page for options for your target OS (i.e. xargs -n.)
Also noting that 'kill -9' is a non-graceful process exit mechanism (i.e. possible file corruption, other strangeness) so I suggest only using as a last resort...
:)

Shell script for logging cpu and memory usage of a linux process

I am looking for a way to log and graphically display cpu and RAM usage of linux processes over time. Since I couldn't find a simple tool to so (I tried zabbix and munin but installation failed) I started writing a shell script to do so
The script file parses the output of top command through awk and logs into a csv file. It
Figures out the pid of the processes through ps command
Uses top and awk to log cpu and memory usage.
Here is how the script looks like
#!/bin/sh
#A script to log the cpu and memory usage of linux processes namely - redis, logstash, elasticsearch and kibana
REDIS_PID=$(ps -ef | grep redis | grep -v grep | awk '{print $2}')
LOGSTASH_PID=$(ps -ef | grep logstash | grep -v grep | awk '{print $2}')
ELASTICSEARCH_PID=$(ps -ef | grep elasticsearch | grep -v grep | awk '{print $2}')
KIBANA_PID=$(ps -ef | grep kibana | grep -v grep | awk '{print $2}')
LOG_FILE=/var/log/user/usage.log
echo $LOG_FILE
top -b | awk -v redis="$REDIS_PID" -v logstash="$LOGSTASH_PID" '/redis|logstash/ {print $1","$9","$10","$12}'
How do I
Print the resource usage for multiple processes. Specifying multiple
variables in the awk pattern is not working. It prints the usage for
the first pid (redis in the above script)
Print current timestamp when printing the resource details (through date +"%T")
Print the process name along with the resource usage. Redis, Logstash, ElasticSearch or Kibana in the above case
Redirect the above commands output to a log file. I tried > $LOG_FILE but it didn't work.
Thoughts/Inputs?
Thanks in advance.
To figure out PIDs you can simplify your script greatly using pgrep:
REDIS_PID=$(pgrep -f redis)
LOGSTASH_PID=$(pgrep -f logstash)
ELASTICSEARCH_PID=$(pgrep -f elasticsearch)
KIBANA_PID=$(pgrep -f kibana)
EDIT: Sorry had to leave for some work and couldn't provide the full answer.
In order to capture top's output use following script:
while :; do
top -n 1 -b | awk -v redis="$REDIS_PID" -v logstash="$LOGSTASH_PID"
'$1 == redis || $1 == logstash {print $1","$9","$10","$12}' >> $LOG_FILE
sleep 3
done

Resources