TIL: Auto-reload a command when files changed using entr

While working with Go and JavaScript, we have tools available for auto reloading the server when the code changes. For JavaScript, we even have hot reload which reloads part of the page without reloading the whole page. But for Python, we don’t have such tools, I tried livereload, but it does not work well for nested directories. So I decided to do it myself. And there is a tool called entr which helps run a command when some file changes.

First, install entr:

apt get entr

It can be used like this, which will run python main.py when any file in the current directory changes, recursively:

find . | entr -r python main.py

But this will only work for changes in existing files, not for new files. To fix this, we can combine with some tricks. Let’s use ls -alR | sha256sum to get a hash of all files in the current directory recursively. And then we can compare the hash to see if any file has changed:

hash() {
  ls -alR | sha256sum
}

hash0="$(hash)"
echo "$hash0" > /tmp/hash.txt
while true; do
  hash1="$(hash)"
  if [[ "$hash0" != "$hash1" ]]; then
    hash0="$hash1"
    echo "$hash1" > /tmp/hash.txt
  fi
done

Here is the final code, enjoy!

#!/bin/bash

hash() {
  ls -alR | grep '\.py$' | sha256sum
}

watch() {
  hash0="$(cat /tmp/hash.txt)"
  while true; do
    hash1="$(hash)"
    if [[ "$hash0" != "$hash1" ]]; then
      printf "\n\n------- restarting server -------\n\n"
      hash0="$hash1"
      echo "$hash1" > /tmp/hash.txt
    fi
    sleep 2
  done
}

if [[ -z "$DEBUG" ]]; then
    echo "$(hash)" > /tmp/hash.txt
    watch &
    echo '/tmp/hash.txt' | entr -r python apps/rpc/app/main.py
else
    python -m debugpy --listen 0.0.0.0:12345 apps/rpc/app/main.py
fi

Author

I'm Oliver Nguyen. A software maker working mostly in Go and JavaScript. I enjoy learning and seeing a better version of myself each day. Occasionally spin off new open source projects. Share knowledge and thoughts during my journey. Connect with me on , , , and .

Back Back