Install Watchman in Ubuntu

This will be a straight forward guide to install Watchman in your Ubuntu 22.04. I am writing it out of frustration after following their official weird installation guide and other guides from here and there.
Just use
sudo apt install watchman
That would be great if we can do that. However, our folks in Meta warned us to use the pre-built deps. Since they are full of security issues and they are not updated so often.
Download it!
I think you can just visit their releases page on GitHub and download it from there. However, you won’t find a .deb
in all releases. In fact most of them don’t have even a Linux version. I don’t know why and I don’t want to know honestly.
However, you can find some with Linux binaries included. You can just download the zip, extract it, and make it executable as they mentioned in their pre-built binaries for Linux documentation here.
Of course not all the releases has those, so you have to search for one. Luckily, ChatGPT knows how to write Bash scripts. You can use this script to get the latest releases with Linux built files in them.
#!/bin/bash
# GitHub API URL for Watchman releases
url="https://api.github.com/repos/facebook/watchman/releases"
# Fetch releases data from GitHub API
releases=$(curl -s $url)
# Parse and filter releases using jq to find those with assets containing "linux" in their names
echo "$releases" | jq -r '
.[] |
select(.assets | any(.name | contains("linux"))) |
{
tag_name: .tag_name,
name: .name,
linux_assets: .assets | map(select(.name | contains("linux"))) | .[]
}
| "Release: \(.tag_name) - \(.name)\nLinux Assets:\n\(.linux_assets.name)\nURL: \(.linux_assets.browser_download_url)\n"
'
But then, you want it to download it for you and install it. You can, using this script:
#!/bin/bash
# Function to print and exit on failure
fail_on_error() {
if [ $? -ne 0 ]; then
echo "Error: $1 step failed."
exit 1
fi
}
# Check for root privileges
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
# Fetch releases data from GitHub API
fetch_releases() {
url="https://api.github.com/repos/facebook/watchman/releases"
releases=$(curl -s $url)
fail_on_error "Fetch releases"
echo "$releases" | jq -r '
.[] |
select(.assets | any(.name | contains("linux"))) |
{
tag_name: .tag_name,
name: .name,
linux_assets: .assets | map(select(.name | contains("linux"))) | .[]
}
| "Release: \(.tag_name) - \(.name)\nLinux Assets:\n\(.linux_assets.name)\nURL: \(.linux_assets.browser_download_url)\n"
'
}
# Prompt user to select a release to download
prompt_release_selection() {
read -p "Enter the URL of the release you want to download: " release_url
wget -q $release_url -O watchman-linux.zip
fail_on_error "Download release"
}
# Install the selected release
install_release() {
unzip watchman-linux.zip
fail_on_error "Unzip release"
release_dir=$(ls -d */ | grep "watchman-v")
cd $release_dir || exit
sudo mkdir -p /usr/local/{bin,lib} /usr/local/var/run/watchman
fail_on_error "Create directories"
sudo cp bin/* /usr/local/bin
fail_on_error "Copy binaries"
sudo cp lib/* /usr/local/lib
fail_on_error "Copy libraries"
sudo chmod 755 /usr/local/bin/watchman
fail_on_error "Set permissions on watchman binary"
sudo chmod 2777 /usr/local/var/run/watchman
fail_on_error "Set permissions on watchman run directory"
echo "Watchman installed successfully."
}
# Fetch releases
fetch_releases
# Prompt for release selection
prompt_release_selection
# Install the selected release
install_release
# Verify installation
watchman --version
fail_on_error "Verify installation"
Even better, you can use the following script to download the latest released version (not the latest but the latest with a Linux build).
#!/bin/bash
# Function to print and exit on failure
fail_on_error() {
if [ $? -ne 0 ]; then
echo "Error: $1 step failed."
exit 1
fi
}
# Check for root privileges
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
# Fetch the latest release data from GitHub API
fetch_latest_release() {
url="https://api.github.com/repos/facebook/watchman/releases"
latest_release=$(curl -s $url | jq -r '
.[] |
select(.assets | any(.name | contains("linux"))) |
{
tag_name: .tag_name,
name: .name,
linux_asset: .assets | map(select(.name | contains("linux"))) | .[0]
} | "\(.tag_name),\(.linux_asset.browser_download_url)"
' | head -n 1)
fail_on_error "Fetch latest release"
if [ -z "$latest_release" ]; then
echo "No suitable Linux release found."
exit 1
fi
tag_name=$(echo $latest_release | cut -d ',' -f 1)
release_url=$(echo $latest_release | cut -d ',' -f 2)
echo "Latest Release: $tag_name"
echo "Downloading from: $release_url"
wget -q $release_url -O watchman-linux.zip
fail_on_error "Download release"
}
# Install the latest release
install_release() {
unzip watchman-linux.zip
fail_on_error "Unzip release"
release_dir=$(ls -d */ | grep "watchman-v")
cd $release_dir || exit
sudo mkdir -p /usr/local/{bin,lib} /usr/local/var/run/watchman
fail_on_error "Create directories"
sudo cp bin/* /usr/local/bin
fail_on_error "Copy binaries"
sudo cp lib/* /usr/local/lib
fail_on_error "Copy libraries"
sudo chmod 755 /usr/local/bin/watchman
fail_on_error "Set permissions on watchman binary"
sudo chmod 2777 /usr/local/var/run/watchman
fail_on_error "Set permissions on watchman run directory"
echo "Watchman installed successfully."
}
# Fetch the latest release
fetch_latest_release
# Install the latest release
install_release
# Verify installation
watchman --version
fail_on_error "Verify installation"
Build it 😐
That’s what most Moodle folks mention in their tutorials. Yep, I need this Watchman to make watching file changes more efficiently my Moodle development environment. Anyway, I tried them all, and none of them worked. All of them ends with an error and I am not wasting time to solve some C++ building errors.
I went through the building actions they have in their Github Workflow. Fetched the dependencies like they are doing in the getdeps_linux
action. Built them and finally run the building command for Watchman. Same things over and over again. Currently it says that CARGO_COMMAND not found using the name cargo
even though I have the Rust toolchain installed and the latest version of cargo. I think I am doing something wrong. I will write about it when I have time.
Meanwhile, I am using the pre-built binaries from their releases.