patternbashMinor
Bash functions to run/manage MySQL, Redis, Sidekiq, Rails server
Viewed 0 times
redissidekiqmanagerailsmysqlserverfunctionsbashrun
Problem
I'm working with a Rails app that requires a few layers of infrastructure to run: MySQL, Redis, Sidekiq, and (of course) the Rails server. I wrote some functions to help me manage the various servers (start/stop/check and one to kill the rails server when it gets hung up and decides to eat all my memory rather than shutting down).
I'm still new to Bash scripting, and looking for all the feedback/criticism I can get, so please, don't hold back. I'm particularly interested in how I can further DRY up this code.
Generic helpers to check if a named process is running and get its pid:
MySQL server:
Redis server:
Sidekiq:
```
function sksta {
if ! running sidekiq; then
sidekiq -d
until running sidekiq; do
sleep 1
done
echo "Sidekiq daemon started"
else
echo "Sidekiq daemon already running"
fi
}
function sksto {
if running sidekiq; then
kill $(rpid sidekiq)
while running sidekiq; do
sleep 1
done
echo "Sidekiq daemon stopped"
else
I'm still new to Bash scripting, and looking for all the feedback/criticism I can get, so please, don't hold back. I'm particularly interested in how I can further DRY up this code.
Generic helpers to check if a named process is running and get its pid:
function running {
pgrep -f "$1" &> /dev/null
}
function rpid {
pgrep -f "$1" 2> /dev/null
}MySQL server:
function msta {
if ! running mysql; then
mysql.server start
else
echo "MySQL already running"
fi
}
function msto {
if running mysql; then
mysql.server stop
else
echo "MySQL not running"
fi
}
function mstat {
if running mysql; then
echo "MySQL running"
else
echo "MySQL not running"
fi
}Redis server:
function resta {
if ! running redis; then
redis-server ~/.redis/redis.conf
until running redis; do
sleep 1
done
echo "Redis daemon started"
else
echo "Redis daemon already running"
fi
}
function resto {
if running redis; then
kill $(rpid redis)
while running redis; do
sleep 1
done
echo "Redis daemon stopped"
else
echo "Redis daemon not running"
fi
}
function restat {
if running redis; then
echo "Redis daemon running"
else
echo "Redis daemon not running"
fi
}Sidekiq:
```
function sksta {
if ! running sidekiq; then
sidekiq -d
until running sidekiq; do
sleep 1
done
echo "Sidekiq daemon started"
else
echo "Sidekiq daemon already running"
fi
}
function sksto {
if running sidekiq; then
kill $(rpid sidekiq)
while running sidekiq; do
sleep 1
done
echo "Sidekiq daemon stopped"
else
Solution
Pretty nicely written! In fact, if you want to DRY this up, I'm pretty sure you could do it yourself if you seriously tried... But here you go anyway ;-)
Non-standard features
The
Write it this way instead:
DRY-ing up
You could write
This way, the
The start / stop / status commands have the common elements of checking if the process is running or not. You could create helper functions to reduce the duplication:
Then you can simplify the MySQL functions using these helpers:
Similarly for redis:
And I left the rest for you as exercise:
There remains still some duplication in the
shellcheck.net
This site is really awesome for checking your shell scripts for common mistakes:
http://www.shellcheck.net/#
Non-standard features
The
function keyword is non-standard:function rpid {
pgrep -f "$1" 2> /dev/null
}Write it this way instead:
rpid() {
pgrep -f "$1" 2> /dev/null
}DRY-ing up
You could write
running in terms of rpid:running() {
rpid "$1" > /dev/null
}
rpid() {
pgrep -f "$1" 2> /dev/null
}This way, the
pgrep logic is only in one place. If you need to change something, you could do it in one place. Just remember that the caller (running) expects the correct exit code of success / failure, and no output on stderr.The start / stop / status commands have the common elements of checking if the process is running or not. You could create helper functions to reduce the duplication:
start() {
procname=$1; shift
name=$1; shift
if ! running "$procname"; then
"$@"
else
echo "$name already running"
fi
}
stop() {
procname=$1; shift
name=$1; shift
if running "$procname"; then
"$@"
else
echo "$name not running"
fi
}
status() {
procname=$1
name=$2
if running "$procname"; then
echo "$name running"
else
echo "$name not running"
fi
}Then you can simplify the MySQL functions using these helpers:
msta() {
start mysql MySQL mysql.server start
}
msto() {
stop mysql MySQL mysql.server stop
}
mstat() {
status mysql MySQL
}Similarly for redis:
redis_start() {
redis-server ~/.redis/redis.conf
until running redis; do
sleep 1
done
}
redis_stop() {
kill $(rpid redis)
while running redis; do
sleep 1
done
}
resta() {
start redis "Redis daemon" redis_start
}
resto() {
stop redis "Redis daemon" redis_stop
}
restat() {
status redis "Redis daemon"
}And I left the rest for you as exercise:
rastatcan be simplified usingstatus
krscan be simplified similar to the way I did redis above
- You can leave
reportkillas it is, as it's a different pattern from the others
There remains still some duplication in the
start, stop, status helpers, but trying to reduce that might hurt readability. I think the current form is the "sweet spot", trying to optimize further will have diminishing returns.shellcheck.net
This site is really awesome for checking your shell scripts for common mistakes:
http://www.shellcheck.net/#
Code Snippets
function rpid {
pgrep -f "$1" 2> /dev/null
}rpid() {
pgrep -f "$1" 2> /dev/null
}running() {
rpid "$1" > /dev/null
}
rpid() {
pgrep -f "$1" 2> /dev/null
}start() {
procname=$1; shift
name=$1; shift
if ! running "$procname"; then
"$@"
else
echo "$name already running"
fi
}
stop() {
procname=$1; shift
name=$1; shift
if running "$procname"; then
"$@"
else
echo "$name not running"
fi
}
status() {
procname=$1
name=$2
if running "$procname"; then
echo "$name running"
else
echo "$name not running"
fi
}msta() {
start mysql MySQL mysql.server start
}
msto() {
stop mysql MySQL mysql.server stop
}
mstat() {
status mysql MySQL
}Context
StackExchange Code Review Q#59603, answer score: 2
Revisions (0)
No revisions yet.