Check if service exists in bash (CentOS and Ubuntu) - linux

What is the best way in bash to check if a service is installed? It should work across both Red Hat (CentOS) and Ubuntu?
Thinking:
service="mysqld"
if [ -f "/etc/init.d/$service" ]; then
# mysqld service exists
fi
Could also use the service command and check the return code.
service mysqld status
if [ $? = 0 ]; then
# mysqld service exists
fi
What is the best solution?

To get the status of one service without "pinging" all other services, you can use the command:
systemctl list-units --full -all | grep -Fq "$SERVICENAME.service"
By the way, this is what is used in bash (auto-)completion (see in file /usr/share/bash-completion/bash_completion, look for _services):
COMPREPLY+=( $( systemctl list-units --full --all 2>/dev/null | \
awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' ) )
Or a more elaborate solution:
service_exists() {
local n=$1
if [[ $(systemctl list-units --all -t service --full --no-legend "$n.service" | sed 's/^\s*//g' | cut -f1 -d' ') == $n.service ]]; then
return 0
else
return 1
fi
}
if service_exists systemd-networkd; then
...
fi
Hope to help.

Rustam Mamat gets the credit for this:
If you list all your services, you can grep the results to see what's in there. E.g.:
# Restart apache2 service, if it exists.
if service --status-all | grep -Fq 'apache2'; then
sudo service apache2 restart
fi

On a SystemD system :
serviceName="Name of your service"
if systemctl --all --type service | grep -q "$serviceName";then
echo "$serviceName exists."
else
echo "$serviceName does NOT exist."
fi
On a Upstart system :
serviceName="Name of your service"
if initctl list | grep -q "$serviceName";then
echo "$serviceName exists."
else
echo "$serviceName does NOT exist."
fi
On a SysV (System V) system :
serviceName="Name of your service"
if service --status-all | grep -q "$serviceName";then
echo "$serviceName exists."
else
echo "$serviceName does NOT exist."
fi

In systemd (especially in Debian), it doesn't seems to work properly using the various answers from here. For some services like pure-ftpd if it's in disabled mode, it will not show up in service list when you trigger this command:
systemctl --all --type service
and when you start again the pure-ftpd with systemctl start pure-ftpd the list will appear again. So listing the service using systemctl --all --type service will not work for all services. Take a look at this for more information.
So, this is the best code so far (improvement from #jehon's answer) to check if a service is exist (even it has status inactive, dead or whatever status it is):
#!/bin/bash
is_service_exists() {
local x=$1
if systemctl status "${x}" 2> /dev/null | grep -Fq "Active:"; then
return 0
else
return 1
fi
}
if is_service_exists 'pure-ftpd'; then
echo "Service found!"
else
echo "Service not found!"
fi
Explanation:
If systemctl status found a service, it must have a text 'Active:' we filter using grep and it would return 0. If there is no 'Active:' text it would return 1.
If systemctl status does not find the 'Active:' text, it will print out a standard error. So, I put redirection 2> /dev/null to redirect the standard error. For example, if you are looking for the non existence service, you would get this error message if you don't put that error redirection:
Unit pure-ftpdd.service could not be found.
We don't want to have the above standard error message if you are doing scripting
EDIT:
Another method is to list out unit files which able to detect disabled service as pointed by #Anthony Rutledge for Debian system:
systemctl list-unit-files --type service | grep -F "pure-ftpd"
But using this method will not always work especially for older system because some unit files might not be detected using this command as explained in here. Also, using this method is slower if you have large unit-files that need to be filtered (as commented by #ygoe about heavy load on a small computer).

To build off of Joel B's answer, here it is as a function (with a bit of flexibility added in. Note the complete lack of parameter checking; this will break if you don't pass in 2 parameters):
#!/bin/sh
serviceCommand() {
if sudo service --status-all | grep -Fq ${1}; then
sudo service ${1} ${2}
fi
}
serviceCommand apache2 status

After reading some systemd man pages ...
https://www.freedesktop.org/software/systemd/man/systemd.unit.html
... and systemd.services(5)....
... and a nice little article ...
https://www.linux.com/learn/understanding-and-using-systemd
I believe this could be an answer.
systemctl list-unit-files --type service
Pipe to awk {'print $1'} to just get a listing of the service units.
Pipe to awk again to get the service names exclusively. Change the field separator to the period with -F.
awk -F. {'print $1'}
In summary:
systemctl list-unit-files --type service | awk {'print $1'} | awk -F. {'print $1'}
With variation and augmentation of the base solution, you can determine the state of your system's services by combining a for loop with systemctl is-active $service.

#!/bin/sh
service=mysql
status=$(/etc/init.d/mysql status)
print "$status"
#echo $status > /var/log/mysql_status_log

var=$(service --status-all | grep -w "$Service")
if [ "output" != "" ]; then
#executes if service exists
else
#executes if service does not exist
fi
$Service is the name of the service you want to know if exists.
var will contain something like
[+] apache2
if the service does exist

if systemctl cat xxx >/dev/null 2>&1; then
echo yes
fi

Try this, as ps command can be used in both Ubuntu&RHEL, this should be work in both platform.
#!/bin/bash
ps cax | grep mysqld > /dev/null
if [ $? -eq 0 ]; then
echo "mysqld service exists"
else
echo "mysqld service not exists"
fi

Related

DOCKER_OPTS are reset after system reboot

I am specifying my TLS certs in /etc/default/docker, like this:
DOCKER_OPTS="-H=unix:// --tlsverify --tlscacert=/etc/docker/mynewca.pem
--tlscert=/etc/docker/mynewcert.pem
--tlskey=/etc/docker/mynewkey.pem -H=0.0.0.0:2376"
However, every time my Docker host restarts, my settings are overridden with the defaults:
DOCKER_OPTS="-H=unix:// --tlsverify --tlscacert=/etc/docker/ca.pem
--tlscert=/etc/docker/cert.pem
--tlskey=/etc/docker/key.pem -H=0.0.0.0:2376"
This means that I can not communiate with the Docker daemon remotely until I reconfigure DOCKER_OPTS and run
sudo service restart docker
upstart is starting the Docker daemon, and it looks like the script section of /etc/init/docker.conf is overriding DOCKER_OPTS, although I can't find where it's getting the defaults from.
script
# modify these in /etc/default/$UPSTART_JOB (/etc/default/docker)
DOCKERD=/usr/bin/dockerd
DOCKER_OPTS=
if [ -f /etc/default/$UPSTART_JOB ]; then
. /etc/default/$UPSTART_JOB
fi
exec "$DOCKERD" $DOCKER_OPTS --raw-logs
end script
# Don't emit "started" event until docker.sock is ready.
# See https://github.com/docker/docker/issues/6647
post-start script
DOCKER_OPTS=
DOCKER_SOCKET=
if [ -f /etc/default/$UPSTART_JOB ]; then
. /etc/default/$UPSTART_JOB
fi
if ! printf "%s" "$DOCKER_OPTS" | grep -qE -e '-H|--host'; then
DOCKER_SOCKET=/var/run/docker.sock
else
DOCKER_SOCKET=$(printf "%s" "$DOCKER_OPTS" | grep -oP -e '(-H|--host)\W*unix://\K(\S+)' | sed 1q)
fi
if [ -n "$DOCKER_SOCKET" ]; then
while ! [ -e "$DOCKER_SOCKET" ]; do
initctl status $UPSTART_JOB | grep -qE "(stop|respawn)/" && exit 1
echo "Waiting for $DOCKER_SOCKET"
sleep 0.1
done
echo "$DOCKER_SOCKET is up"
fi
end script
Which
You may want to use the docker configuration file that is usually located in /etc/docker/daemon.json. See here for more information on the configuration:
https://docs.docker.com/engine/reference/commandline/dockerd//#daemon-configuration-file
In your case, the "tlscacert" option might be of special interest.
Nevertheless, the location of the configuration file may really depend on the OS and distribution (I remember the famous Gentoo /etc/conf.d/ directory)

Command to detect if elastic search is active in linux

I have to detect if elastic search is running on Linux. If it is not running than start it machine using shell script.
Used following code to detect if elastic search is running, but every time else condition is executed even if service is running:
service=elasticsearch
if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
echo "$service is running!!!"
else
echo "$service is not running!!!"
fi
Here is a sample script and used in a shell script to check if my sevice is running:
Take a look at this script to see if it helps you.
#verify if the service is running
ps aux | grep SERVICENAME | pidof java > /dev/null
verifier=$?
zero=0
if [ $zero = $verifier ]
then
echo "Service was successfully started"
else
echo "Service stopped"
fi
In my case my service was done in java then I use the pidof to properly filter my service
The issue with checking for pid is that the service might have started, but it might not be ready actually. So instead, I check for port that ES is listening on. It works better for me.
netstat -uplnt | grep :9200 | grep LISTEN > /dev/null
verifier=$?
if [ 0 = $verifier ]
then
echo "ES is listening on port 9200"
else
echo "ES is not ready yet"
fi

Remove chkconfig header from output

On my CentOS machine I wrote a script which tells me whether a service is installed or not.
Here is the script
count=$(chkconfig --list | grep -c "$1")
if [ $count = 0 ]; then
echo "False"
else
echo "True"
fi
The problem is that the output of the command always includes the starting lines of the chkconfig output. For example here is the output of script.sh network
[root#vm ~]# ./script.sh network
Note: This output shows SysV services only and does not include native
systemd services. SysV configuration data might be overridden by native
systemd configuration.
If you want to list systemd services use 'systemctl list-unit-files'.
To see services enabled on particular target use
'systemctl list-dependencies [target]'.
True
It seems that the count variable correctly contains the count of grep occurrences but the script will always output the chkconfig header lines, even though I echo only "True" or "False" in the script.
Why does this happen? And how to hide those lines?
This is because chkconfig --list initially returns a header through stderr. Just silence it by using 2>/dev/null:
count=$(chkconfig --list 2>/dev/null | grep -c "$1")
# ^^^^^^^^^^^
Note also that the whole if / else block can be reduced to a mere:
chkconfig --list 2>/dev/null | grep -q "$1" && echo "True" || echo "False"
Since we use the -q option of grep which (from man grep) does exit immediately with zero status if any match is found.

Linux self-healing script to check some process

Im new with Linux scripts, I need help to create one script with check some installed processes on a server and if one of these services is not running restart it, and recheck again those services and if there any error print it with echo as below :
dsisrv (DSI service) (7384) Running
midaemon (measurement interface) (1412) Running
misrv (measurement interface service) (1384) Running
perfalarm (Alarm generator) Stopped
perfalarmsrv (Alarm generator service) Stopped
scopent (data collector) Stopped
scopesrv (collector service) Stopped
perfd (Real Time Metric Access Daemon) (7888) Running
perfdsrv (Real Time Metric Access Service) (9020) Running
ttd (transaction tracking) (1808) Running
in case any of above services is stopped, the script to run restart command.
Appreciate if any one help me to start with this script
Regards,
#!/bin/sh
SERVICE='httpd'
if ps ax | grep -v grep | grep $SERVICE > /dev/null
then
echo "$SERVICE service running, everything is fine"
else
echo "$SERVICE is not running" echo "$SERVICE is not running!" | mail -s "$SERVICE down" root
fi
Just add the service your looking for, this will mail you if the service goes down. Im assuming your using bash so enjoy.
i did simple script i hope this will be helpful please run this script as a root and add your services or daemons inside declaration array
declare -a service=(vsftpd sshd)
full script
#!/bin/bash
declare -a service=(vsftpd sshd) ##declaration array
for x in ${service[#]} ##array with
do
process=` ps -A | grep $x | awk '{print $4}' ` ### all process output
all_services=`echo $x`
line_no=` ps -A | sed -n '/'$all_services'/=' `
if ` ps -A | grep ${process[#]} > 0 ` ## condition to check if service available or not
then
echo "status running", " `ps -A | sed -n ''$line_no''p | awk ' {print $1 $4}'` " ## service up running
else
service $all_services start ### start the daemon again
fi
done

Bash script to stop ssh and smbd depending on SSID

My bash scripting skills are very rusty (it's been ~10 years since I scripted regularly). So, I'm probably overlooking something obvious. I am trying to get the following script to work:
#!/bin/bash
SSID=$(iwgetid -r)
if [[ $SSID = NETWORK ]]; then
if (( $(ps aux | grep [s]shd | wc -l) > 0 )); then
sudo service ssh stop
if (( $(ps aux | grep [s]mdb | wc -l) > 0 )); then
sudo service smbd stop
if (( $(ps aux | grep [n]mdb | wc -l) > 0 )); then
sudo service nmbd stop
else
echo You are not connected to NETWORK
fi
fi
fi
fi
exit 0
What it should do: If I am connected to particular network (SSID removed from script), check to see if ssh, smbd, and nmbd are running, and if so, stop them. If they aren't, do nothing. If not connected to the network, say so and exit. Bash seems to be ignoring the last 2 if...then statements, and I'm not sure why (Wrong order maybe? Conditional formatting incorrect?)
Any help would be appreciated. Also, if you have style tips, I'll take those too (like I said, I'm very rusty). I spent a few hours looking around here and Google, but couldn't find anything relevant and helpful.
You almost certainly meant to do this:
SSID=$(iwgetid -r)
if [[ $SSID = NETWORK ]]; then
if (( $(ps aux | grep [s]shd | wc -l) > 0 )); then
sudo service ssh stop
fi
if (( $(ps aux | grep [s]mdb | wc -l) > 0 )); then
sudo service smbd stop
fi
if (( $(ps aux | grep [n]mdb | wc -l) > 0 )); then
sudo service nmbd stop
fi
else
echo You are not connected to NETWORK
fi
But there is no real cost to running service stop on something which is not running, so you can simplify:
SSID=$(iwgetid -r)
if [[ $SSID = NETWORK ]]; then
sudo service ssh stop
sudo service smbd stop
sudo service nmbd stop
else
echo You are not connected to NETWORK
fi
Finally, I would recommend not using sudo inside the script. Instead, run the script itself with sudo check_ssid (or whatever it is called), so that the script ends up being:
SSID=$(iwgetid -r)
if [[ $SSID = NETWORK ]]; then
service ssh stop
service smbd stop
service nmbd stop
else
echo You are not connected to NETWORK
fi
By the way, if you really want to use ps and grep to check if a process is running, consider my answer here: How to test if a process is running with grep in bash?

Resources