a green reptile's eyes

Simple Directory Watcher to Restart Dev Server

Published on:

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.

Read more

person on air traffic control tower

Deeply Question if You Control Something

pyton, nodejs, php, c# icons with a laptop in the background

What Projects to Do as a Beginner Programmer