I am running a shell script which restarts my app when certain files change. However, when I run the app via a script, a call to enter the debugger no longer works, I think because the app is now running in the background, while the shell script is the foreground.
The debugger works just fine without this script. This all runs inside a Docker container, but I don’t think that’s relevant since the app is being run with docker-compose run
which attaches a terminal.
The script, which I inherited in this codebase, is as follows:
#!/bin/sh
trap Terminate SIGINT SIGTERM SIGQUIT SIGKILL
Start () {
echo "------- Entrypoint: starting app"
bundle exec puma -C dev/puma.rb &
echo $! > /tmp/entrypoint_process.pid
}
Stop () {
echo "------- Entrypoint: stopping app"
kill `cat /tmp/entrypoint_process.pid`
rm /tmp/entrypoint_process.pid
}
Terminate () {
Stop
echo "------- Entrypoint: terminating"
exit 0
}
Restart () {
Stop
Start $@
WatchForChanges $@
}
WatchForChanges () {
echo "------- Entrypoint: watching for changes"
# Watch for files that are:
# - Not handled by the Loader.
# - Don’t require an external action (e.g. a change to the Gemfile needs `docker-compose run signup3 bundle install` to be run before it’s worth triggering a restart).
#
inotifywait -r -q -e modify \
boot.rb \
config.ru \
Gemfile.lock \
services/loader.rb
Restart $@
}
WatchForChanges $@ & Start $@
wait
I believe the ampersand at the end of bundle exec puma -C dev/puma.rb &
is the ‘problem’, because it runs the app in the background. But if I remove it the PID is not stored (because it blocks within Start ()
) and so Stop
fails, and then Start
fails too because the app tries to bind to the same port as the already-running copy of itself.
Is there a reliable way to get this working?
Update:
Having removed the &
along with echo $! > /tmp/entrypoint_process.pid
, I modified Stop ()
to kill the app without a PID using this:
kill $(ps aux | grep '[p]uma' | awk '{print $2}')
(Based on this Q&A)
This works to some extent: if the app tries to drop into the debugger before this script triggers Restart ()
then it succeeds. However, once the app has been restarted by the script it again fails to drop into the debugger as before.
Is there something about the way the functions are being called that causes the app process to be put in the background again when the script runs?
I tried making the calls inside Restart ()
match the initial call to WatchForChanges $@ & Start $@
, but that didn’t help.