How to kill all processes named "shairport" that do not have the pid 12345 - linux

I am using shairport at work to stream music. I am running it on a Debian machine(a raspberry). In its /etc/init.d/shairport file it has only the start|stop commands.
I want to add a restart one. Here is the code so far:
case "$1" in
restart)
service shairport stop
service shairport start
;;
start)
/usr/local/bin/shairport -d -a "$NAME" -p 5002 -k "madafaka" -w -B "mpc stop"
;;
stop)
killall shairport
;;
*)
echo "Usage: /etc/init.d/shairport {start|stop|restart}"
exit 1
;;
esac
exit 0
The issue is that when I run "service shairport restart", the service is stopped, thus running "killall shairport" and killing the bash script process itself. So "start" is never executed.
How do I make killall kill every shairport except the current script?
My idea was to get the pid and exclude it, but I cant find how to do that.

The start part should write down the PID of the started process.
Something like echo $? > /var/run/shairport.pid will do.
Stop part of your script will use the PID from the .pid file we have created, and kill the right process. This is what most of Linux services do as far as I know.

In linux you can know the process ID that the script file is running under with : $$.
You just have to check you're not killing yourself with :
stop)
for pid in $(pgrep shairport); do
if[$pid != $$]
kill $pid
fi
done

Since the answer I chose did not work straight out of the box, here is the code I ended up with:
case "$1" in
restart)
for pid in $(pgrep shairport); do
if [ "$pid" != $$ ]; then
kill $pid
fi
done
/usr/local/bin/shairport -d -a "$NAME" -p 5002 -k "madafaka" -w -B "mpc stop"
;;
start)
/usr/local/bin/shairport -d -a "$NAME" -p 5002 -k "madafaka" -w -B "mpc stop"
;;
stop)
killall shairport
;;
*)
echo "Usage: /etc/init.d/shairport {start|stop|restart}"
exit 1
;;
esac

Related

How to create a service on linux Centos 6

How to create service on centos 6 to kill service and run script
For example :
If i run this command service test start
it should make the below
pkill test
nohup ./opt/test/test/bin/standalone.sh -c standalone-full.xml
Also if i run this command service test stop
it should make the below
pkill test
Create a file like /etc/init.d/test
#!/bin/bash
start() {
/usr/bin/kill -9 $(cat /tmp/test_nohup_pid.txt)
nohup ./opt/test/test/bin/standalone.sh -c standalone-full.xml 2>&1 &
echo $! > /tmp/test_nohup_pid.txt
}
stop() {
/usr/bin/kill -9 $(cat /tmp/test_nohup_pid.txt)
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac

Script guide to prevent duplicate execution of jar in Linux

Jar should run in the background and not run redundantly.
Even if duplicate execution occurs, all must be terminated
#!/bin/bash
ENV=dev
SER_NAME=batch
JAR_FULL=/was/batch/test.jar
case $1 in
restart)
if apid=$(pgrep -f $SER_NAME)
then
for pid in $apid; do
echo "Stop $SER_NAME pid : $pid"
kill -9 $pid
done
else
echo "$SER_NAME is not running ... "
fi
nohup java -jar $JAR_FULL --spring.profiles.active=$ENV > /dev/null 2>&1 &
echo "$SER_NAME" start"
;;
stop)
if apid=$(pgrep -f $SER_NAME)
then
for pid in $apid; do
echo "Stop $SER_NAME - pid : $pid"
kill -9 $pid
done
else
echo "$SER_NAME is not running ..."
fi
;;
start)
if apid=$(pgrep -f $SER_NAME)
then
echo "$SER_NAME is already running ..."
for pid in $apid; do
echo "Running $SER_NAME -pid : $pid"
done
else
nohup java -jar $JAR_FULL --spring.profiles.active=$ENV > /dev/null 2>&1 &
echo "$SER_NAME start!"
fi
;;
esac
example) run.sh
console) chmod 755 run.sh
console) ./run.sh start
start or stop or restart

My custom init shell script stops deployment script

I have a deployment script which works fine. At the end of it I added this block:
cat << EOF > /etc/init.d/uwsgi
#!/bin/bash
daemon=$APPVENV/bin/uwsgi
args="--emperor $APPCONF/uwsgi/app.ini --daemonize /var/log/emperor.log --emperor-pidfile $APPDIR/emperor.pid --gid `id -g $APPUSER`"
pid=$APPDIR/emperor.pid
case "$1" in
start)
echo "Starting uwsgi"
start-stop-daemon -p $pid --start --exec $daemon -- $args
;;
stop)
echo "Stopping script uwsgi"
start-stop-daemon --signal INT -p $pid --stop $daemon -- $args
;;
reload)
echo "Reloading conf"
kill -HUP $(cat $pid)
;;
*)
echo "Usage: /etc/init.d/uwsgi {start|stop|reload}"
exit 1
;;
esac
exit 0
EOF
Now when I run my deployment script it gets stuck here, and I just see a blinking cursor and it doesn't run any lines after it.
Have I done anything wrong with my formatting, as I know creating a file with cat was something very picky about how it was formatted, tabulated etc.
variables are still substituted in heredocs, also subshelling with $( ), which you do in your script here:
kill -HUP $(cat $pid)
your installer attempts to cat that file, with $pid probably empty, therefore it waits for input from standard input.
You want to escape those "$" to prevent expansion, like
\$(cat \$foo)
And of course with all those variables you don't want to get expanded during installation too.

Init.d script doesn't start or stop only prints help message

I've tried to write a custom upstart script for uwsgi emperor but it doesn't seem to start uwsgi and only says Usage: /etc/init.d/uwsgi {start|stop|reload} when I try to run it using "service uwsgi start".
Can anyone please tell me where I have gone wrong. The snippet below is from my deployment shell script:
cat <<EOF >/etc/init.d/uwsgi
#!/bin/bash
daemon=\$APPVENV/bin/uwsgi
args="--emperor \$APPCONF/uwsgi/app.ini --daemonize /var/log/emperor.log --emperor-pidfile \$APPDIR/emperor.pid --gid `id -g \$APPUSER`"
pid=\$APPDIR/emperor.pid
case "$1" in
start)
echo "Starting uwsgi"
start-stop-daemon -m -p \$pid --start --exec \$daemon \$args
;;
stop)
echo "Stopping script uwsgi"
start-stop-daemon --signal INT -p \$pid --stop \$daemon \$args
;;
reload)
echo "Reloading conf"
kill -HUP \$(cat \$pid)
;;
*)
echo "Usage: /etc/init.d/uwsgi {start|stop|reload}"
exit 1
;;
esac
exit 0
EOF
chmod u+x /etc/init.d/uwsgi
update-rc.d uwsgi defaults
service uwsgi start
Use the following. Pay close attention to which $ I escape and do not escape.
cat <<EOF >/etc/init.d/uwsgi
#!/bin/bash
daemon="$APPVENV/bin/uwsgi"
args=( --emperor "$APPCONF/uwsgi/app.ini"
--daemonize /var/log/emperor.log
--emperor-pidfile "$APPDIR/emperor.pid" --gid \$(id -g "$APPUSER")
)
pid="$APPDIR/emperor.pid"
case "\$1" in
start)
echo "Starting uwsgi"
start-stop-daemon -m -p \$pid --start --exec \$daemon \$args
;;
stop)
echo "Stopping script uwsgi"
start-stop-daemon --signal INT -p \$pid --stop \$daemon \$args
;;
reload)
echo "Reloading conf"
kill -HUP \$(< \$pid)
;;
*)
echo "Usage: /etc/init.d/uwsgi {start|stop|reload}"
exit 1
;;
esac
exit 0
EOF
chmod u+x /etc/init.d/uwsgi
update-rc.d uwsgi defaults
service uwsgi start
Variables like APPDIR, based on your previous questions, are used to configure what is actually written to disk, so you leave them unescaped so that they are expanded when /etc/init.d/uwsgi is written.
Variables like daemon, $1, and the command substitutions $(id -g "$APPUSER") are intended to be expanded when the init script runs, so you want the literal string $daemon to appear in the script, not the value of $daemon (which is probably undefined) when uwsgi is written.
You forgot to escape the $1 like you did in other places in your script:
case "\$1" in
As you are using cat to create the script, you need to escape all instances of $
Check if the service start really does send an argument to your script:
*)
echo "Argument taken was \"$1\"."
echo "Usage: /etc/init.d/uwsgi {start|stop|reload}"
exit 1
It could actually be different and you may consider making changes based from it.

Linux Script to check if process is running and act on the result

I have a process that fails regularly & sometimes starts duplicate instances..
When I run:
ps x |grep -v grep |grep -c "processname"
I will get:
2
This is normal as the process runs with a recovery process..
If I get
0
I will want to start the process
if I get:
4
I will want to stop & restart the process
What I need is a way of taking the result of ps x |grep -v grep |grep -c "processname"
Then setup a simple 3 option function
ps x |grep -v grep |grep -c "processname"
if answer = 0 (start process & write NOK & Time to log /var/processlog/check)
if answer = 2 (Do nothing & write OK & time to log /var/processlog/check)
if answer = 4 (stot & restart the process & write NOK & Time to log /var/processlog/check)
The process is stopped with
killall -9 process
The process is started with
process -b -c /usr/local/etc
My main problem is finding a way to act on the result of ps x |grep -v grep |grep -c "processname".
Ideally, I would like to make the result of that grep a variable within the script with something like this:
process=$(ps x |grep -v grep |grep -c "processname")
If possible.
Programs to monitor if a process on a system is running.
Script is stored in crontab and runs once every minute.
This works with if process is not running or process is running multiple times:
#! /bin/bash
case "$(pidof amadeus.x86 | wc -w)" in
0) echo "Restarting Amadeus: $(date)" >> /var/log/amadeus.txt
/etc/amadeus/amadeus.x86 &
;;
1) # all ok
;;
*) echo "Removed double Amadeus: $(date)" >> /var/log/amadeus.txt
kill $(pidof amadeus.x86 | awk '{print $1}')
;;
esac
0 If process is not found, restart it.
1 If process is found, all ok.
* If process running 2 or more, kill the last.
A simpler version. This just test if process is running, and if not restart it.
It just tests the exit flag $? from the pidof program. It will be 0 of process is running and 1 if not.
#!/bin/bash
pidof amadeus.x86 >/dev/null
if [[ $? -ne 0 ]] ; then
echo "Restarting Amadeus: $(date)" >> /var/log/amadeus.txt
/etc/amadeus/amadeus.x86 &
fi
And at last, a one liner
pidof amadeus.x86 >/dev/null ; [[ $? -ne 0 ]] && echo "Restarting Amadeus: $(date)" >> /var/log/amadeus.txt && /etc/amadeus/amadeus.x86 &
This can then be used in crontab to run every minute like this:
* * * * * pidof amadeus.x86 >/dev/null ; [[ $? -ne 0 ]] && echo "Restarting Amadeus: $(date)" >> /var/log/amadeus.txt && /etc/amadeus/amadeus.x86 &
cccam oscam
I adopted the #Jotne solution and works perfectly! For example for mongodb server in my NAS
#! /bin/bash
case "$(pidof mongod | wc -w)" in
0) echo "Restarting mongod:"
mongod --config mongodb.conf
;;
1) echo "mongod already running"
;;
esac
I have adopted your script for my situation Jotne.
#! /bin/bash
logfile="/var/oscamlog/oscam1check.log"
case "$(pidof oscam1 | wc -w)" in
0) echo "oscam1 not running, restarting oscam1: $(date)" >> $logfile
/usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1 &
;;
2) echo "oscam1 running, all OK: $(date)" >> $logfile
;;
*) echo "multiple instances of oscam1 running. Stopping & restarting oscam1: $(date)" >> $logfile
kill $(pidof oscam1 | awk '{print $1}')
;;
esac
While I was testing, I ran into a problem..
I started 3 extra process's of oscam1 with this line:
/usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1
which left me with 8 process for oscam1. the problem is this..
When I run the script, It only kills 2 process's at a time, so I would have to run it 3 times to get it down to 2 process..
Other than killall -9 oscam1 followed by /usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1, in *)is there any better way to killall apart from the original process? So there would be zero downtime?
If you changed awk '{print $1}' to '{ $1=""; print $0}' you will get all processes except for the first as a result. It will start with the field separator (a space generally) but I don't recall killall caring. So:
#! /bin/bash
logfile="/var/oscamlog/oscam1check.log"
case "$(pidof oscam1 | wc -w)" in
0) echo "oscam1 not running, restarting oscam1: $(date)" >> $logfile
/usr/local/bin/oscam1 -b -c /usr/local/etc/oscam1 -t /usr/local/tmp.oscam1 &
;;
2) echo "oscam1 running, all OK: $(date)" >> $logfile
;;
*) echo "multiple instances of oscam1 running. Stopping & restarting oscam1: $(date)" >> $logfile
kill $(pidof oscam1 | awk '{ $1=""; print $0}')
;;
esac
It is worth noting that the pidof route seems to work fine for commands that have no spaces, but you would probably want to go back to a ps-based string if you were looking for, say, a python script named myscript that showed up under ps like
root 22415 54.0 0.4 89116 79076 pts/1 S 16:40 0:00 /usr/bin/python /usr/bin/myscript
Just an FYI
The 'pidof' command will not display pids of shell/perl/python scripts. So to find the process id’s of my Perl script I had to use the -x option i.e. 'pidof -x perlscriptname'
I cannot get case to work at all.
Heres what I have:
#! /bin/bash
logfile="/home/name/public_html/cgi-bin/check.log"
case "$(pidof -x script.pl | wc -w)" in
0) echo "script not running, Restarting script: $(date)" >> $logfile
# ./restart-script.sh
;;
1) echo "script Running: $(date)" >> $logfile
;;
*) echo "Removed duplicate instances of script: $(date)" >> $logfile
# kill $(pidof -x ./script.pl | awk '{ $1=""; print $0}')
;;
esac
rem the case action commands for now just to test the script. the above pidof -x command is returning '1', the case statement is returning the results for '0'.
Anyone have any idea where I'm going wrong?
Solved it by adding the following to my BIN/BASH Script:
PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
In case you're looking for a more modern way to check to see if a service is running (this will not work for just any old process), then systemctl might be what you're looking for.
Here's the basic command:
systemctl show --property=ActiveState your_service_here
Which will yield very simple output (one of the following two lines will appear depending on whether the service is running or not running):
ActiveState=active
ActiveState=inactive
And if you'd like to know all of the properties you can get:
systemctl show --all your_service_here
If you prefer that alphabetized:
systemctl show --all your_service_here | sort
And the full code to act on it:
service=$1
result=`systemctl show --property=ActiveState $service`
if [[ "$result" == 'ActiveState=active' ]]; then
echo "$service is running" # Do something here
else
echo "$service is not running" # Do something else here
fi
If you are using CentOS, no need to write a script and set cron job. Here is one of the smartest ways to ensure systemd services restart on failure.
Make following changes to /usr/lib/systemd/system/mariadb.service
Then under the [Service] section in the file, add the following 2 lines:
Restart=always
RestartSec=3
After saving the file we need to reload the daemon configurations to ensure systemd is aware of the new file
systemctl daemon-reload
Read the following link for the complete steps -
https://jonarcher.info/2015/08/ensure-systemd-services-restart-on-failure/

Resources