Bash: Continuously check processes running or not with some parameters - linux

I want to create script that will check continuously process status running or not. If process will not run, script should catch it and restart it in a seconds. How can I run continuously this script on the system and how should I change the script via ---> Important points: it should take as parameters these: 1-seconds to wait between attempts to restart service, 2- number of attempts and 3- generate logs of events. Nginx is a example for the process. It can be replaceable.
#!/bin/bash
SERVICE="nginx"
if pgrep -x "$SERVICE" >/dev/null
then
echo "$SERVICE is running"
else
echo "$SERVICE stopped"
# start nginx if stopped
echo "$SERVICE starting"
systemctl start $SERVICE
fi

You can try something like this:
#!/bin/bash
service="nginx"
seconds=2
retries=3
until (( retries-- == 0 ))
do
property=$(systemctl show --property MainPID "$service")
if [[ $property == MainPID=0 ]]
then
echo "$service stopped"
echo "$service starting"
systemctl start "$service" >& /dev/null
else
echo "$service is running"
exit
fi
sleep "$seconds"
done
echo "$service is broken"

Related

Bash exit status not working in script

I've written a script that starts, stops and sends status of Apache, with messages dependent on the output of the commands.
I have most of it correct, but my errors are not printing out correctly. In other words, even if I do not have Apache loaded, "stopping" it still shows a successful message.
I need help getting my error messages to print when necessary.
#!/bin/bash
echo -e "\e[1;30mApache Web Server Control Script\e[0m"
echo
echo "Enter the operation number to perform (1-4): "
echo " 1 - Start the httpd server"
echo " 2 - Restart the httpd server"
echo " 3 - Stop the httpd server"
echo " 4 - Check httpd server status"
echo
echo -n "===> "
read NUMBER
EXITSTATUS=$?
echo
if [ $NUMBER -eq "1" ]; then
systemctl start httpd
if [ $EXITSTATUS -eq "0" ]; then
echo -e "\e[1;32mThe return value of the command 'systemctl
start httpd' was 0.\e[0m"
echo -e "\e[1;32mThe Apache web server was successfully
started.\e[0m"
else
echo -e "\e[1;31mThe return value of the command 'systemctl
start httpd' was 5.\e[0m"
echo -e "\e[1;31mThe Apache web server was not successfully
started.\e[0m"
fi
fi
if [ $NUMBER -eq "2" ]; then
systemctl restart httpd
if [ $EXITSTATUS -eq "0" ]; then
echo -e "\e[1;32mThe return value of the command 'systemctl
restart httpd' was 0.\e[0m"
echo -e "\e[1;32mThe Apache web server was successfully
restarted.\e[0m"
else
echo -e "\e[1;31mThe return value of the command 'systemctl
restart httpd' was 5.\e[0m"
echo -e "\e[1;31mThe Apache web server was not successfully
restarted.\e[0m"
fi
fi
if [ $NUMBER -eq "3" ]; then
systemctl stop httpd
if [ $EXITSTATUS -eq "0" ]; then
echo -e "\e[1;32mThe return value of the command 'systemctl
stop httpd' was 0.\e[0m"
echo -e "\e[1;32mThe Apache web server was successfully
stopped\e[0m."
else
echo -e "\e[1;31mThe return value of the command 'systemctl
stop httpd' was 5.\e[0m"
echo -e "\e[0;31mThe Apache web server was successfully
stopped.\e[0m"
fi
fi
if [ $NUMBER -eq "4" ]; then
systemctl status httpd
if [ $EXITSTATUS -eq "0" ]; then
msg=$(systemctl status httpd)
else
echo -e "\e[1;31mThe Apache web server is not currently
running.\e[0m"
echo $(msg)
fi
fi
if [[ $NUMBER != [1-4] ]]; then
echo -e "\e[1;31mPlease select a valid choice: Exiting.\e[0m"
fi
exit 0
The variable EXITSTATUS doesn't contain the exit code of the systemctl calls, but that of the read command. You could rewrite it either as
systemctl start httpd
EXITSTATUS=$?
if [ $EXITSTATUS -eq 0 ]; then
[...]
or more simply as
systemctl start httpd
if [ $? -eq 0 ]; then
[...]
Storing the value of $? in a variable is only necessary if you either want to use it afterwards in another place (e. g. as exit code of your own script), or have to make other calls before branching on the value.
You're not setting your variable $EXITSTATUS after running the commands, so it maintains its original value (the exit status of read NUMBER).
Since you only care about whether the command succeeded or not, better would be to avoid using it entirely and change the conditions to e.g.:
if systemctl restart httpd; then
# it was successful ($? would be 0)
fi

Linux Script to check if process is running and restart if not

I am having this script which looks for the process filebeat and restarts it if is not running. Cron runs this script every 5 minutes. Most of the time this works fine except sometime it creates multiple filebeat process. Can someone please point out what is the issue in my script.
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
service=filebeat
servicex=/usr/share/filebeat/bin/filebeat
pid=`pgrep -x "filebeat"`
if [ $pid > /dev/null ]
then
echo "$(date) $service is running!!!"
else
echo "$(date) starting $service"
cd /home/hpov/beats/filebeat
./filebeat -c filebeat.yml &
fi
#!/bin/bash
pidof script.x86 >/dev/null
if [[ $? -ne 0 ]] ; then
echo "Restarting script: $(date)" >> /var/log/script.txt
/etc/script/script.x86 &
fi
Super easy :D

can shell script make itself run in background after running some steps?

I have BBB based custom Embedded Linux based board with busybox shell(ash)
I have a situation where my script must run in background with following condition
There must only one instance of the script.
wrapper script need to know if script started successfully in background or not.
There is another wrapper script which starts and stops my script, wrapper script is as mentioned below.
#!/bin/sh
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
readonly TEST_SCRIPT_PATH="/home/testscript.sh"
readonly TEST_SCRIPT_LOCK_PATH="/var/run/${TEST_SCRIPT_PATH##*/}.lock"
start_test_script()
{
local pid_of_testscript=0
local status=0
#Run test script in background
"${TEST_SCRIPT_PATH}" &
#---------Now When this point is hit, lock file must be created.-----
if [ -f "${TEST_SCRIPT_LOCK_PATH}" ];then
pid_of_testscript=$(head -n1 ${TEST_SCRIPT_LOCK_PATH})
if [ -n "${pid_of_testscript}" ];then
kill -0 ${pid_of_testscript} &> /dev/null || status="${?}"
if [ ${status} -ne 0 ];then
echo "Error starting testscript"
else
echo "testscript start successfully"
fi
else
echo "Error starting testscript.sh"
fi
fi
}
stop_test_script()
{
local pid_of_testscript=0
local status=0
if [ -f "${TEST_SCRIPT_LOCK_PATH}" ];then
pid_of_testscript=$(head -n1 ${TEST_SCRIPT_LOCK_PATH})
if [ -n "${pid_of_testscript}" ];then
kill -0 ${pid_of_testscript} &> /dev/null || status="${?}"
if [ ${status} -ne 0 ];then
echo "testscript not running"
rm "${TEST_SCRIPT_LOCK_PATH}"
else
#send SIGTERM signal
kill -SIGTERM "${pid_of_testscript}"
fi
fi
fi
}
#Script starts from here.
case ${1} in
'start')
start_test_script
;;
'stop')
stop_test_script
;;
*)
echo "Usage: ${0} [start|stop]"
exit 1
;;
esac
Now actual script "testscript.sh" looks something like this,
#!/bin/sh
#Filename : testscript.sh
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
set -eu
LOCK_FILE="/var/run/${0##*/}.lock"
FLOCK_CMD="/bin/flock"
FLOCK_ID=200
eval "exec ${FLOCK_ID}>>${LOCK_FILE}"
"${FLOCK_CMD}" -n "${FLOCK_ID}" || exit 0
echo "${$}" > "${LOCK_FILE}"
# >>>>>>>>>>-----Now run the code in background---<<<<<<
handle_sigterm()
{
# cleanup
"${FLOCK_CMD}" -u "${FLOCK_ID}"
if [ -f "${LOCK_FILE}" ];then
rm "${LOCK_FILE}"
fi
}
trap handle_sigterm SIGTERM
while true
do
echo "do something"
sleep 10
done
Now in above script you can see "---Now run the code in background--" at that point I am sure that either lock file is successfully created or instance of this script is already running. So Then I can safely run other code in background and wrapper script can check for lockfile and find out if the process mentioned in the lock file is running or not.
can shellscript itself make it to run in background ?
if not is there a better way to meet all the conditions ?
I think you can look into job control built-in, specifically bg.
Job Control Commands
When processes say they background themselves, what they actually do is fork and exit the parent. You can do the same by running whichever commands, functions or statements you want with & and then exiting.
#!/bin/sh
echo "This runs in the foreground"
sleep 3
while true
do
sleep 10
echo "doing background things"
done &

how to capture command error message in variable for if block

Hi below is my code for bash shell script, in this I want to capture error message for if clause, when it says either job is already running or unable to start the job to a variable, how it is possible in below script, or any other way for the below functionality
if initctl start $i ; then
echo "service $i started by script"
else
echo "not able to start service $i"
fi
You can for example use the syntax msg=$(command 2>&1 1>/dev/null) to redirect stderr to stdout after redirecting stdout to /dev/null. This way, it will just store stderr:
error=$(initctl start $i 2>&1 1>/dev/null)
if [ $? -eq 0 ]; then
echo "service $i started by script"
else
echo "service $i could not be started. Error: $error"
fi
This uses How to pipe stderr, and not stdout?, so that it catches stderr from initctl start $i and stores in $error variable.
Then, $? contains the return code of the command, as seen in How to check if a command succeeded?. If 0, it succeeded; otherwise, some errors happened.
Use '$?' variable
It stores any exit_code from the previous statement
See http://www.tldp.org/LDP/abs/html/exitcodes.html for more information
initctl start $i
retval=$?
if [ $retval -eq 0 ]; then
echo "service $i started by script"
else
echo "not able to start service $i"
fi

Code seems to duplicate processes when in a cron job

I have a problem with my shell code. The purpose of the code is to automatically start the server if one is suddenly is offline due to a crash. The code works perfectly when you just simply execute it via ./script.sh & however! When I set a cron job with the script, it begins to start several processes of the srvexecutable
Unfortunately the processes have the same name, so I have to base it off the process ID and the process ID's location. Hence "realpath" is implemented.
Here is the code. I would extremely appreciate it if someone helped me fix this bug.
# Created by Lorenc!
# Server List
srvloc_1="/home/user/srv1"
server_1="/home/user/srv1/srvexecutable"
srvloc_2="/home/user/srv2"
server_2="/home/user/srv2/srvexecutable"
# Loop Iterator And Server Array!
servers=0
declare -a SRV
for word in $(pidof srvexecutable); do
SRV[servers]="$(realpath /proc/$word/exe)"
#echo ${SRV[$servers]}
let servers++
done
if [ "$servers" -ge 2 ]; then
echo "that's $servers processes"
exit
else
if [ "$servers" -le 1 ];
then
echo "Currently $servers processes."
if [ "$servers" -eq 0 ];
then
echo "No servers online! Booting both now."
cd $srvloc_1
nohup $server_1 &
sleep 1
cd $srvloc_2
nohup $server_2 &
exit
else
if ${SRV[0]} == $server_1
then
echo "Starting $server_1 as it is not online!"
cd $srvloc_1
nohup $server_1 &
else
echo "Starting $server_2 as it is not online!"
cd $srvloc_2
nohup $server_2 &
fi
fi
else
echo "Both servers are running. Beautiful."
fi
fi

Resources