Last active
February 25, 2025 14:35
-
-
Save wmertens/4df207197074f9cb93f003c1cb723b4c to your computer and use it in GitHub Desktop.
Wrap a command with an SQLite read lock on given files so they can safely be backed up
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# This script wraps a command with a read lock on given SQLite databases | |
# Example: wrap-sqlite-backup.sh *.sqlite3 -- tar cvzf backup.tgz *.sqlite3 | |
# | |
# Note that it doesn't check for errors, so it really only works in WAL mode. | |
# Updates that read from ${COPROC[0]} to check errors welcome. | |
# | |
# [email protected] | |
# https://gist.github.com/wmertens/4df207197074f9cb93f003c1cb723b4c | |
# exit on any error | |
set -e | |
DBs= | |
while [ -n "$1" ] && [ "$1" != "--" ]; do | |
DBs="$DBs $1" | |
shift | |
done | |
if [ "$1" != "--" ]; then | |
echo "Usage: $0 sqliteDbFiles... -- command args..." >&2 | |
exit 1 | |
fi | |
shift | |
# We run the sqlite CLI in a coprocess and acquire read locks on all DBs | |
coproc sqlite3 | |
# We can send command on this fd. We're ignoring the output fd. | |
I=${COPROC[1]} | |
function close() { | |
echo ".quit" >&$I | |
wait | |
} | |
# Try to close coproc on script exit | |
trap close 0 | |
for i in $DBs; do | |
n=$(basename "$i") | |
echo "ATTACH DATABASE '$i' AS \"$n\"; PRAGMA \"$n\".wal_checkpoint(FULL);" >&$I | |
done | |
echo "BEGIN;" >&$I | |
for i in $DBs; do | |
n=$(basename "$i") | |
# This is enough to acquire a read lock | |
echo "SELECT 1 FROM \"$n\".sqlite_master;" >&$I | |
done | |
# Now wait for the command to complete | |
# Since this is the last command, it will determine the exit code | |
"${@}" | |
# The trap above will close sqlite3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment