Skip to content

Instantly share code, notes, and snippets.

@uberdragon
Last active May 3, 2019 08:43
Show Gist options
  • Save uberdragon/fd8ce6e37c37518eefea5276b180e655 to your computer and use it in GitHub Desktop.
Save uberdragon/fd8ce6e37c37518eefea5276b180e655 to your computer and use it in GitHub Desktop.
Bash script to start multiple rails apps at once, each in their own named terminal tab using chruby, gnome-terminal & the BASH_POST_RC trick. Save this in your ~/bin folder. First app gets port 3000, 2nd gets 3001, etc. Tested with Ubuntu 18.04.
#~/bin/rdev
#!/bin/bash
###############################################################################
# author: Shane Kretzmann
# email: Shane.Kretzmann@gmail.com
# gist: https://gist.github.com/uberdragon/fd8ce6e37c37518eefea5276b180e655
#
# Description:
# Bash script to start multiple rails apps at once, each in their own named terminal
# tab using chruby, gnome-terminal & the BASH_POST_RC trick. Save this in your ~/bin
# folder. First app gets port 3000, 2nd gets 3001, etc. Tested with Ubuntu 18.04.
#
# Usage Examples:
#
# start all rails apps
# ~/> rdev start
#
# start a single rails app
# ~/> rdev start app port
#
# stop all rails apps
# ~/> rdev stop
#
# stop a single rails app
# ~/> rdev stop app port
#
# restart a single rails app
# ~/> rdev restart app port
###############################################################################
#
# collection of rails apps you want to start in development (should match directory name of rails project)
# note: the first app in the collection will receive port 3000, the second 3001 and so on
#
rails_apps=(app1 app2 app3 etc)
#
# The root directory of your rails projects
#
projects_root="~/ruby/projects/root/path"
#
# This is the maximum amount of time (in seconds) the script should wait for an
# app to boot If a rails app doesn't load within this max wait time it will
# report the rails app boot sequence as a failure and move on to the next app.
#
max_wait=15 #seconds
#
###############################################################################
# Don't touch anything below here unless you know what you are doing.
###############################################################################
ok="...\e[1m\e[92mok!\e[0m"
skipped="...\e[93mskipped!\e[0m"
failed="...\e[1m\e[91mfailed!\e[0m"
validate_port () {
valid_port="^[0-9]{4}$"
if ! [[ $1 ]]; then
echo -e "\e[1m\e[31mERROR:\e[0m\e[2m Missing port number\e[0m..."; echo;
print_help
exit 1
fi
if ! [[ $1 =~ $valid_port ]]; then
echo -e "\e[1m\e[31mERROR:\e[0m\e[2m Invalid port number\e[0m..."; echo;
print_help
exit 1
fi
}
port_test () {
validate_port $1
if [[ $(lsof -wni tcp:$1) ]]; then
if [[ $2 ]]; then
skip=TRUE
else
echo -e "port in use$failed"; echo;
lsof -wni tcp:$1
exit 1
fi
fi
}
test_rails_up () {
app=$1; port=$2; i=0
unset result
while [ $i -lt $max_wait ]; do
((i++))
if [[ $(lsof -wni tcp:$port) ]]; then
if $(kill -0 $(cat $project/tmp/pids/server.pid) &> /dev/null); then
result=$ok
break
fi
fi
echo -n "."
sleep 1
done
if [[ $result ]]; then
echo -e $result
else
echo -e "waited $max_wait seconds$failed"
fi
}
check_bashrc () {
if ! [[ $(tail -n 2 ~/.bashrc | grep BASH_POST_RC) ]]; then
echo -en "missing BASH_POST_RC...attempting to patch ~/.bashrc with \e[1meval \"\$BASH_POST_RC\"\e[0m..."
if $(echo "eval \"\$BASH_POST_RC\" # must stay at bottom of .bashrc to work" >> ~/.bashrc); then
echo -e $ok
else
echo -e $failed
echo -e "\e[1m\e[31mERROR:\e[0m\e[2m Missing BASH_POST_RC. \e[0mAdd the following manually to the \e[5mlast\e[0m line of your .bashrc: \e[1meval \"\$BASH_POST_RC\"\e[0m then, run this command again."
exit 1
fi
fi
}
start () {
app=$1; port=$2
eval project="$projects_root/$app"
check_bashrc
echo -en "setting up environment for \e[1m$app\e[0m app..."
unset skip; port_test $port $3
if [[ $skip ]]; then
echo -e "port $port in use$skipped"
elif [[ -d $project ]]; then
echo -en "starting rails on port \e[1m$port\e[0m."
pushd $project &> /dev/null
gnome-terminal --tab --title="$app $port" -- bash -c "export BASH_POST_RC=\"chruby $(cat .ruby-version); source .env; bundle exec rails s -p $port; exit\"; exec bash"
test_rails_up $app $port
popd &> /dev/null
else
echo -e "rails project not found at $project$failed"
fi
}
stop () {
app=$1; port=$2
eval project="$projects_root/$app"
validate_port $port
echo -en "shutting down \e[1m$app\e[0m app..."
if [[ -d $project ]]; then
if $(kill -0 $(cat $project/tmp/pids/server.pid) &> /dev/null); then
sleep 1
kill -9 $(cat $project/tmp/pids/server.pid)
result=$ok
sleep 1
if [[ $(lsof -wni tcp:$port) ]]; then
result="port $port still in use$failed";
show_running_port=TRUE
fi
else
result="server already stopped$ok"
fi
else
result="rails project not found at $project$failed"
fi
echo -e $result
if [[ $show_running_port ]]; then
lsof -wni tcp:$port; echo;
fi
}
print_help () {
echo "$(basename -- "$0") - a simple command to manage multiple rails servers in development"
echo " Usage: $(basename -- "$0") {start|stop|restart} [app port]"
}
case "$1" in
start)
app=$2; port=$3
if [[ $app ]]; then
start $app $port
else
port=3000 # starting port
for app in "${rails_apps[@]}"; do
start $app $port '--with-skip'
((port++))
done
echo; echo -e "\e[2mRails development environment boot sequence complete.\e[0m"
fi
;;
stop)
app=$2; port=$3
if [[ $app ]]; then
stop $app $port
else
port=3000
for app in "${rails_apps[@]}"; do
stop $app $port
((port++))
done
echo; echo -e "\e[2mRails development environment shut down complete.\e[0m"
fi
;;
restart)
app=$2; port=$3
stop $app $port
start $app $port
;;
*)
print_help
exit 1
;;
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment