patternbashMinor
Small bash script to start and stop named services
Viewed 0 times
scriptnamedstopservicessmallstartandbash
Problem
I've been working on ubuntu since many years but not quite familiar with bash scripting. My development tools involve servers like nginx and apache, the mysql database and beanstalkd. Obviously, I just can't keep all these services running always and overwhelm my CPU capacity!, so I need a way of starting a bunch of these services without having to write poetry like:
Hence I've written this script called kick (no laughs!), so I can just pass it some parameters and say:
Since the starting mechanism of each of these services are different, I had to deal each one in a separate if condition. I would like to know from you bash experts whether this is the correct way to do it:
filename: kick
```
#!/bin/bash
function docmd()
{
#echo 'func',"$1","$2"
if [ "$1" = "nginx" ];
then
if [ "$2" = "sh" ]; then
/home/prahlad/programs/nginx-1.6.0/sbin/nginx -s stop
elif [ "$2" = "re" ]; then
/home/prahlad/programs/nginx-1.6.0/sbin/nginx
sleep 1
/home/prahlad/programs/nginx-1.6.0/sbin/nginx -s stop
else
/home/prahlad/programs/nginx-1.6.0/sbin/nginx
fi
elif [ "$1" = "php-fpm" ]
then
if [ "$2" = "sh" ]; then
pkill php-fpm
elif [ "$2" = "re" ]; then
pkill php-fpm
sleep1
/home/prahlad/programs/php-5.4/sbin/php-fpm
else
/home/prahlad/programs/php-5.4/sbin/php-fpm
fi
elif [ "$1" = "apache2" ]
then
if [ "$2" = "sh" ]; then
sudo service apache2 stop
elif [ "$2" = "re" ]; then
sudo service apache2 restart
else
sudo service apache2 start
fi
elif [ "$1" = "mysql" ]
then
if [ "$2" = "sh" ]; then
sudo service mysql stop
elif [ "$2" = "re" ]; the
sudo service apache2 start
sudo service mysql start
..blah blah..Hence I've written this script called kick (no laughs!), so I can just pass it some parameters and say:
kick start apache2 mysql
# OR
kick stop nginx php-fpmSince the starting mechanism of each of these services are different, I had to deal each one in a separate if condition. I would like to know from you bash experts whether this is the correct way to do it:
filename: kick
```
#!/bin/bash
function docmd()
{
#echo 'func',"$1","$2"
if [ "$1" = "nginx" ];
then
if [ "$2" = "sh" ]; then
/home/prahlad/programs/nginx-1.6.0/sbin/nginx -s stop
elif [ "$2" = "re" ]; then
/home/prahlad/programs/nginx-1.6.0/sbin/nginx
sleep 1
/home/prahlad/programs/nginx-1.6.0/sbin/nginx -s stop
else
/home/prahlad/programs/nginx-1.6.0/sbin/nginx
fi
elif [ "$1" = "php-fpm" ]
then
if [ "$2" = "sh" ]; then
pkill php-fpm
elif [ "$2" = "re" ]; then
pkill php-fpm
sleep1
/home/prahlad/programs/php-5.4/sbin/php-fpm
else
/home/prahlad/programs/php-5.4/sbin/php-fpm
fi
elif [ "$1" = "apache2" ]
then
if [ "$2" = "sh" ]; then
sudo service apache2 stop
elif [ "$2" = "re" ]; then
sudo service apache2 restart
else
sudo service apache2 start
fi
elif [ "$1" = "mysql" ]
then
if [ "$2" = "sh" ]; then
sudo service mysql stop
elif [ "$2" = "re" ]; the
Solution
Don't Repeat Yourself
You start/stop/restart apache2 and mysql the same way, so you don't need to duplicate their code. You could create a generalized function that can handle these or any standard service well, like this:
Naming
You renamed the universal and intuitive command names start/stop/restart to the shorter but kind of obscure st/sh/re. I recommend to stick with the originals. Among other things, the
The case statement
The case statement in Bash is more concise and easier to read than many if-elif-elif-else statements, for example:
Minor things
Suggested implementation
Here's an alternative implementation using the above suggestions:
Notice that
As @vnp pointed out, the
The bigger picture
Ideally, you should standardize everything: make it possible to start/stop/restart your custom
You start/stop/restart apache2 and mysql the same way, so you don't need to duplicate their code. You could create a generalized function that can handle these or any standard service well, like this:
startstop_service() {
cmd=$1
name=$2
sudo service $name $cmd
}Naming
You renamed the universal and intuitive command names start/stop/restart to the shorter but kind of obscure st/sh/re. I recommend to stick with the originals. Among other things, the
startstop_service in my previous point will work out of the box.The case statement
The case statement in Bash is more concise and easier to read than many if-elif-elif-else statements, for example:
case "$1" in
start|stop|restart) cmd=$1 ;;
*) echo "usage: $0 [start|stop|restart] servicenames"; exit 1
esac
shiftMinor things
- Your script doesn't use any Bash specific features,
/bin/shwould be enough
- It's better to validate the
cmdparameter once, instead of for every single service name as in your code
- If the
cmdis invalid, it's good to exit the script with a non-zero exit code (typicallyexit 1), to indicate failure
- You can simplify
for name in "$@"; doasfor name; do
Suggested implementation
Here's an alternative implementation using the above suggestions:
#!/bin/sh -e
NGINX=/home/prahlad/programs/nginx-1.6.0/sbin/nginx
PHP=/home/prahlad/programs/php-5.4/sbin/php-fpm
PHP_NAME=$(basename $PHP)
startstop_service() {
cmd=$1
name=$2
sudo service $name $cmd
}
startstop_nginx() {
cmd=$1
case $cmd in
stop) $NGINX -s stop ;;
start) $NGINX ;;
restart)
$NGINX -s stop
sleep 1
$NGINX
;;
esac
}
startstop_php() {
cmd=$1
case $cmd in
stop) pkill $PHP_NAME ;;
start) $PHP ;;
restart)
pkill $PHP_NAME
sleep 1
$PHP
;;
esac
}
case "$1" in
start|stop|restart) cmd=$1 ;;
*)
shift
servicenames=${@-servicenames}
echo "usage: $0 [start|stop|restart] $servicenames"
exit 1
esac
shift
for name; do
case "$name" in
php-fpm) startstop_php $cmd ;;
nginx) startstop_nginx $cmd ;;
*) startstop_service $cmd $name ;;
esac
doneNotice that
apache2 and mysql are not even mentioned in this script, they are automatically handled by the generic startstop_service function. The script will work with any other standard service too.As @vnp pointed out, the
sleep 1 calls are dodgy, I did not fix that. To fix that, look for pid files created by those services, and use them to check if the service is still running or not.The bigger picture
Ideally, you should standardize everything: make it possible to start/stop/restart your custom
php-fpm and nginx just like other services. That way you can remove the service-specific logic from this script (doesn't really belong here anyway), and then it can work for any service you throw at it. Unfortunately I don't know enough Ubuntu to guide you, but I'm sure the guys on askubuntu.com can help with that.Code Snippets
startstop_service() {
cmd=$1
name=$2
sudo service $name $cmd
}case "$1" in
start|stop|restart) cmd=$1 ;;
*) echo "usage: $0 [start|stop|restart] servicenames"; exit 1
esac
shift#!/bin/sh -e
NGINX=/home/prahlad/programs/nginx-1.6.0/sbin/nginx
PHP=/home/prahlad/programs/php-5.4/sbin/php-fpm
PHP_NAME=$(basename $PHP)
startstop_service() {
cmd=$1
name=$2
sudo service $name $cmd
}
startstop_nginx() {
cmd=$1
case $cmd in
stop) $NGINX -s stop ;;
start) $NGINX ;;
restart)
$NGINX -s stop
sleep 1
$NGINX
;;
esac
}
startstop_php() {
cmd=$1
case $cmd in
stop) pkill $PHP_NAME ;;
start) $PHP ;;
restart)
pkill $PHP_NAME
sleep 1
$PHP
;;
esac
}
case "$1" in
start|stop|restart) cmd=$1 ;;
*)
shift
servicenames=${@-servicenames}
echo "usage: $0 [start|stop|restart] $servicenames"
exit 1
esac
shift
for name; do
case "$name" in
php-fpm) startstop_php $cmd ;;
nginx) startstop_nginx $cmd ;;
*) startstop_service $cmd $name ;;
esac
doneContext
StackExchange Code Review Q#55077, answer score: 7
Revisions (0)
No revisions yet.