Simple Directory Watcher to Restart Dev Server
Tömő Viktor
Posted on June 27, 2024
Simple Linux script that restarts the dev server on file changes. Couldn't find it so I made it.
Intro
I have been learning Go and I came across a pretty basic problem. I was practicing making a REST API web server and I wanted to enable hot reloading so my changes would be visible while I am changing the code. This is a common workflow when using a development server.
Ever since I have been making APIs there was always a simple way to enable hot reloading. It is easy in Go too, you just have to use air. It so simple, just write air
and you have hot reloading. Now you may ask the question that if it's so great what this post is for?
My script
It all started when air
decided to freeze multiple times. I searched a few and found no quick solution so I started to think about a solution. By my understanding air basically just executes the command that runs the web server (in this case go run .
).
Do I really need a whole Go library to do that? There must be a lighter or in other words Linux solution. I came across few solutions but not all had the capability to handle all types of directory changes. I wanted to be able to watch for file: create, edit, move, delete. For example entr
doesn't rerun the command when a new file is added to the directory that is being watched.
Then I discovered inotify-tools
and inside it inotifywait
. This tool can do all kinds of file changes that I wanted. So now I only had to create a script which can run the specified command and also is able to kill the process and rerun the command.
The script takes whatever args are passed into it and runs that and restarts it whenever a file change happens in the current directory. I also made it so via --we-exclude=[PATHS]
you can pass inotify what to exlude from watching.
#!/usr/bin/env zsh
if ! command -v inotifywait > /dev/null; then
print -P "%F{red}Can't start: inotifywait not found.%f"
exit
fi
we_exclude_value=""
command_to_exec=""
for arg in "$@"; do
if [[ $arg == "--we-exclude="* ]]; then
we_exclude_value="${arg#*=}"
break
else
command_to_exec+="$arg "
fi
done
command_to_exec=${command_to_exec% }
while true; do
print -P "$(date +%T): %F{green}Restarting...%f"
$@ &
PID=$!
inotifywait --event=modify,move,create,delete,delete_self --recursive . --exclude=$we_exclude_value > /dev/null 2>&1
pkill -P $PID 2>/dev/null
kill $PID 2>/dev/null
wait $PID 2>/dev/null
done
The script is also available in my GitHub .dotfiles repository under the scripts directory.
If you are interested in more of this type of content then I suggest you to read posts from my series about improving my setup and developer productivity.
Posted on June 27, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.