Restart a process when cpu gets high - bash

I've got a cron job checking for webserver (seeing if its active), which is handy..
http://pastebin.com/raw.php?i=KW8crfzh
I'm wanting after something similar for cpu usage. I'm running java backend which occasionally gets 70%+ cpu. I'm after a cron script to automatically kill/restart java if cpu load gets too high, how is this possible?

You could use top in batch mode coupled with some code to parse its output. For example:
top -p 1234 -n 1 -b
Will output a snapshot of the state of process 1234.

I use this script and it is pretty cool
#!/bin/bash
# author = Jaysunn
# Log
LOGFILE=/var/log/load_kill_log
# log the process causing the load at the time.
PSFILE=/var/log/ps_log
# Obtain the server load
loadavg=`uptime |cut -d , -f 4|cut -d : -f 2`
thisloadavg=`echo $loadavg|awk -F \. '{print $1}'`
if [ "$thisloadavg" -ge "10" ]; then
ps auxfww >> $PSFILE
date >> $LOGFILE
# Issue the command of choice. This can be any shell command.
## Put the command which restarts ..
fi
give executable permissions and add this to crontab with proper path to this script.

Related

cronjob not executing script as expected

I have this script running on a Juniper router which essentially is running Freebsd 10. Problem i am facing is the when cronjob is running this script variable ($current_mem) doesn't show any value as a result logger is also not able to log that value. Anyone have any clue what is going on.
#!/bin/bash
localpid=$$
renice -n +1 $localpid &
current_mem="test"
echo "$current_mem" <<<<shows right value
current_mem=$(cli -c "show task memory" | grep "Currently In Use" | awk
'{print $5}' | grep -o '[0-9]*')
echo "$current_mem" <<<<<<<<<<"when cron is running it show's nothing"
if [ "$current_mem" -gt "65" ]
then
echo "$current_mem" <<<<<"shows nothing"
logger -t JTASK_OS_MEM_HIGH -p "external.notice" "Using more then 65
percent of available memory Current utilization:$current_mem" <<<<<
else
echo "$current_mem"
logger -t JTASK_OS_MEM_NORMAL -p "external.notice" "Using less then 65
percent of available memory Current utilization: $current_mem"
fi
When i run this script with sh task_mem.sh, script works perfectly but when i run it through cron it doesn't show/dump the value of variable. This what i have for the cron job
# crontab -l
*/1 * * * * sh /var/tmp/task_mem.sh >>
/var/tmp/task_mem_cron.log
#GordonDavisson that was it "cli" was in /usr/sbin/cli not in /bin as a result cron was not able to execute it. Once i added the full path it started working. Thank you so much for your help

Docker kill an infinite process in a container after X amount of time

I am using the code found in this docker issue to basically start a container run a process within 20 seconds and if the process completes / does not complete / fails to execute / times out the container is killed regardless.
The code I am using currently is this:
#!/bin/bash
set -e
to=$1
shift
cont=$(docker run -d "$#")
code=$(timeout "$to" docker wait "$cont" || true)
docker kill $cont &> /dev/null
echo -n 'status: '
if [ -z "$code" ]; then
echo timeout
else
echo exited: $code
fi
echo output:
# pipe to sed simply for pretty nice indentation
docker logs $cont | sed 's/^/\t/'
docker rm $cont &> /dev/null
Which is almost perfect however if you run an infinite process (for example this python infinite loop):
while True:
print "inifinte loop"
The whole system jams up and the app crashes, after reading around a bit I think it has something to do with the STDOUT Buffer but I have absolutely no idea what that means?
The problem you have is with a process that is writing massive amounts of data to stdout.
These messages get logged into a file which grows infinitely.
Have a look at (depending on your system's location for log files):
sudo find /var/lib/docker/containers/ -name '*.log' -ls
You can remove old log files if they are of no interest.
One possibility is to start your docker run -d daemon
under a ulimit restriction on the max size a file can be.
Add to the start of your script, for example:
ulimit -f 20000 -c 0
This limits file sizes to 20000*1024 bytes, and disables core file dumps, which you expect
to get from infinite loops where writes are forced to fail.
Please add & at the end of
cont=$(docker run -d "$#")&
It will run the process in background.
I don't know dockers but if it still fail to stop you may also add just after this line the following :
mypid=$!
sleep 20 && kill $mypid
Regards

Terminal Application to Keep Web Server Process Alive

Is there an app that can, given a command and options, execute for the lifetime of the process and ping a given URL indefinitely on a specific interval?
If not, could this be done on the terminal as a bash script? I'm almost positive it's doable through terminal, but am not fluent enough to whip it up within a few minutes.
Found this post that has a portion of the solution, minus the ping bits. ping runs on linux, indefinitely; until it's actively killed. How would I kill it from bash after say, two pings?
General Script
As others have suggested, use this in pseudo code:
execute command and save PID
while PID is active, ping and sleep
exit
This results in following script:
#!/bin/bash
# execute command, use '&' at the end to run in background
<command here> &
# store pid
pid=$!
while ps | awk '{ print $1 }' | grep $pid; do
ping <address here>
sleep <timeout here in seconds>
done
Note that the stuff inside <> should be replaces with actual stuff. Be it a command or an ip address.
Break from Loop
To answer your second question, that depends in the loop. In the loop above, simply track the loop count using a variable. To do that, add a ((count++)) inside the loop. And do this: [[ $count -eq 2 ]] && break. Now the loop will break when we're pinging for a second time.
Something like this:
...
while ...; do
...
((count++))
[[ $count -eq 2 ]] && break
done
ping twice
To ping only a few times, use the -c option:
ping -c <count here> <address here>
Example:
ping -c 2 www.google.com
Use man ping for more information.
Better practice
As hek2mgl noted in a comment below, the current solution may not suffice to solve the problem. While answering the question, the core problem will still persist. To aid to that problem, a cron job is suggested in which a simple wget or curl http request is sent periodically. This results in a fairly easy script containing but one line:
#!/bin/bash
curl <address here> > /dev/null 2>&1
This script can be added as a cron job. Leave a comment if you desire more information how to set such a scheduled job. Special thanks to hek2mgl for analyzing the problem and suggesting a sound solution.
Say you want to start a download with wget and while it is running, ping the url:
wget http://example.com/large_file.tgz & #put in background
pid=$!
while kill -s 0 $pid #test if process is running
do
ping -c 1 127.0.0.1 #ping your adress once
sleep 5 #and sleep for 5 seconds
done
A nice little generic utility for this is Daemonize. Its relevant options:
Usage: daemonize [OPTIONS] path [arg] ...
-c <dir> # Set daemon's working directory to <dir>.
-E var=value # Pass environment setting to daemon. May appear multiple times.
-p <pidfile> # Save PID to <pidfile>.
-u <user> # Run daemon as user <user>. Requires invocation as root.
-l <lockfile> # Single-instance checking using lockfile <lockfile>.
Here's an example of starting/killing in use: flickd
To get more sophisticated, you could turn your ping script into a systemd service, now standard on many recent Linuxes.

Running df -k command for my application server,and it is having mount issue,so need to trigger a mail

I an running df -k command for my application server, and it is having mount issue.
So I need to trigger a mail saying that the server is having mount issue.
My basic question, I will write a shell script which will run df -k command and identify if the command takes long time to complete the command, then I need to trigger a mail.
How can I do this ?
This question lists ways to detect stale NFS mounts: Is there a good way to detect a stale NFS mount
Select one solution and run it before the df -k.
Alternatively, you can redirect stderr to stdout and then grep for the error pattern:
df -k 2>&1 | grep ...error...
if [[ $? -ne 0 ]]; then
...send mail...
fi
It's not clear what exactly you're trying to archive; but timing how long a command takes is fairly easy, for example:
#!/bin/sh
start=$(date +%s)
out=$(sleep 6)
took=$(($(date +%s) - $start))
if [ $took -gt 5 ]; then
echo "$out" | mail -s "Command took too long" test#example.com
fi
Edit
This required the command to finish; if you want to have a timeout, I'd recommend using Python. It is possible with shell scripting, but IMHO this is much easier.
#!/usr/bin/env python
import subprocess, smtplib
from email.mime.text import MIMEText
proc = subprocess.Popen(['sleep', '100'])
try:
proc.wait(5) # 5 is the timeout in seconds
except subprocess.TimeoutExpired:
proc.kill()
# Send email
msg = MIMEText("Command took too long\r\n")
msg['Subject'] = 'Command took too long'
msg['From'] = 'test#example.com'
msg['To'] = 'test#example.com'
s = smtplib.SMTP('localhost')
s.sendmail('test#example.com', ['test#example.com'], msg.as_string())
s.quit()

CRON job and bash script to check battery state and beep

I recently changed desktop environments and the new one doesn't have a battery monitor.
I had managed to create a simple manual one by doing the following:
alias bat='upower -i /org/freedesktop/UPower/devices/battery_BAT0| grep -E "state|to\ full|percentage"'
I would like to take this to the next level and create a script that not only checks the battery level but also beeps according to it, lets say it will beep if the battery percent is less then 20%.
I would then like to run it as CRON job, which lets say will run every 5 minutes.
I also used the following to create a beep sound which I liked:
alias beep='paplay /usr/share/sounds/ubuntu/stereo/message-new-instant.ogg'
Assuming the CRON part is covered, how would you write this script in bash, assuming you use the same command as used in 'bat':
upower -i /org/freedesktop/UPower/devices/battery_BAT0
thanks
I came up with the following solution:
1) Create a bash script:
#!/bin/bash
bat='upower -i /org/freedesktop/UPower/devices/battery_BAT0| grep -E "state|to\ full|percentage"'
beep='paplay /usr/share/sounds/ubuntu/stereo/message-new-instant.ogg'
# This gets the integer percentage of current battery capacity
p=$(eval $bat | grep 'percentage' | awk '{print $2}' | awk -F '.' '{print $1}')
# if bat < 25% -> BEEP once
if [ "$p" -le 25 ] ; then
eval $beep
fi
2) Set the permissions:
chmod 700 /path/to/script.sh
3) To set a cron job run crontab -e and add the following line:
*/1 * * * * /path/to/script.sh
which means the script will be run every minute.

Resources