Assistance with While condition for backup script

196 views
Skip to first unread message

David Schulz

unread,
Sep 21, 2026, 7:22:44 PMSep 21
to weewx-user
Hi
I'm attempting to write my first bash script to backup weewx.  I'm struggling with the syntax of a condition for a while loop that checks if weewx has stopped or is still stopping.

I don't really understand the syntax of the example conditions I can find for various tutorials on using while to create a loop.  I cannot find anywhere an exact example of using 'systemctl is-active' as the condition for a while loop.

Appreciate any feedback from people more learned than I.

TIA 

Here's what I have at the moment.  If I run this script when I know weewx won't be writing to the database, the commands to zip the files into the backup directory all work OK.

I don't think I want to be copying the database file in the middle of a write.  So I have a separate script with the backup section removed just trying to test the stopping, check has stopped and start parts of the script.  I've been unsuccessfully futzing around with different condition syntax and actively trying to run it when weewx is active and the stop command will take a while to execute while the weewx main loop completes.  But TBH I'm just wandering about in the dark.  

```
#!/bin/bash
#
# Stop weewx service
echo $(date): Weewx is stopping >> /var/log/weewx-backup.log
systemctl stop weewx
#
# Check service has stopped
while [ systemctl -q is-active weewx ];
do
        sleep 1
        echo $(date): Weewx is still stopping >> /var/log/weewx-backup.log
done
echo $(date): Weewx has stopped >> /var/log/weewx-backup.log
#
# Copy files to backup folder
echo $(date): Backup is starting >> /var/log/weewx-backup.log
tar -czvf /mnt/backup/weewx-conf.tar.gz /etc/weewx
tar -czvf /mnt/backup/weewx-db.tar.gz /var/lib/weewx/weewx.sdb
echo $(date): Backup is complete >> /var/log/weewx-backup.log
#
# Start weewx service
systemctl start weewx
echo $(date): Weewx is starting >> /var/log/weewx-backup.log
```

David Schulz

unread,
Sep 21, 2026, 7:24:07 PMSep 21
to weewx-user
OK, That's not how you do a code block here - apologies.  And no edit!?!?!

Vince Skahan

unread,
Sep 21, 2026, 7:41:27 PMSep 21
to weewx-user
There's no need to stop weewx in my experience so you don't need any while loop.

This one comes up periodically every year or so and there are 'many' threads with pointers to other folks' scripts and approaches in the archives of this google group.  That said, I do it a couple ways - I do nightly copies (gzipped) of all my databases - and I do occasional copies of all the pertinent software excluding databases.

Here are my two scripts for a 'pip' installation.  Hopefully the comments are self-explanatory.  I renamed them to end in .txt to make clicking to read them easier.   Note the 'exclude' in the script that backs up the software itself which skips backing up the database(s) which the other script handles nightly.
backup-weewx-software.sh.txt
weewx-backup-copy.sh.txt

David Schulz

unread,
Sep 21, 2026, 8:06:28 PMSep 21
to weewx-user
Thanks Vince

I appreciate you sharing your approaches.  

John Bonzey

unread,
Sep 21, 2026, 8:06:31 PMSep 21
to weewx...@googlegroups.com
Claude says the following;

Subject: Re: bash while loop syntax for weewx backup script

Hi,

I think I spotted the issue. Your while condition is:

while [ systemctl -q is-active weewx ];

The problem is that [ ... ] is the "test" command - it doesn't actually run systemctl at all. It just checks whether the string "systemctl -q is-active weewx" is non-empty, which is always true, so the loop never ends based on weewx's real state (it just happens to work when weewx stops quickly, since the loop body still runs and eventually you get lucky with timing).

The fix is to drop the [ ] brackets entirely and use the command itself as the condition. In bash, while just checks the exit status of whatever command you give it - it doesn't need [ ] at all unless you're testing a string, number, or file:

while systemctl -q is-active weewx;
do
        sleep 1
        echo $(date): Weewx is still stopping >> /var/log/weewx-backup.log
done

systemctl -q is-active weewx exits 0 (true) while the service is active, and non-zero once it's fully stopped - which is exactly what you want the loop to check.

General rule of thumb: use while [ condition ] for string/number/file tests, and while some_command when you want to "loop while this command succeeds."

Your instinct not to copy the DB mid-write is exactly right, and this fix makes that work as intended.

One more suggestion: it's worth adding a timeout guard in case weewx ever hangs on stop, so the script can't wait forever. Here's the full script with that added:

#!/bin/bash
#
# Stop weewx service
echo $(date): Weewx is stopping >> /var/log/weewx-backup.log
systemctl stop weewx
#
# Check service has stopped (with timeout)
timeout=30
count=0
while systemctl -q is-active weewx;
do
        if [ $count -ge $timeout ]; then
                echo $(date): Weewx did not stop after ${timeout}s - aborting backup >> /var/log/weewx-backup.log
                systemctl start weewx
                exit 1
        fi
        sleep 1
        count=$((count + 1))
        echo $(date): Weewx is still stopping >> /var/log/weewx-backup.log
done
echo $(date): Weewx has stopped >> /var/log/weewx-backup.log
#
# Copy files to backup folder
echo $(date): Backup is starting >> /var/log/weewx-backup.log
tar -czvf /mnt/backup/weewx-conf.tar.gz /etc/weewx
tar -czvf /mnt/backup/weewx-db.tar.gz /var/lib/weewx/weewx.sdb
echo $(date): Backup is complete >> /var/log/weewx-backup.log
#
# Start weewx service
systemctl start weewx
echo $(date): Weewx is starting >> /var/log/weewx-backup.log

With the timeout added, if weewx ever fails to stop within 30 seconds, the script restarts weewx, logs the failure, and exits before touching the backup files - so a hung stop can't leave weewx down or risk copying a database mid-write.

Hope that helps!

From: weewx...@googlegroups.com <weewx...@googlegroups.com> on behalf of David Schulz <davidjs...@gmail.com>
Sent: Monday, September 21, 2026 7:22 PM
To: weewx-user <weewx...@googlegroups.com>
Subject: [weewx-user] Assistance with While condition for backup script
 
--
You received this message because you are subscribed to the Google Groups "weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to weewx-user+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/weewx-user/df76a922-ace3-44ae-a65a-0a50b6f8fe92n%40googlegroups.com.

Vince Skahan

unread,
Sep 21, 2026, 8:51:02 PMSep 21
to weewx-user
Please no three page AI drivel. Please.

John Bonzey

unread,
Sep 21, 2026, 8:55:03 PMSep 21
to weewx-user
How is it drivel.  it gives the completed script with an explanation

Pablo Sanchez

unread,
Sep 21, 2026, 9:47:49 PMSep 21
to weewx...@googlegroups.com
I found the Gen AI response on point.

What's more disconcerting would be a single person dictating what is and what isn't allowed to be posted to a worldwide list.
---
pablo

Warren Gill

unread,
Sep 21, 2026, 10:59:55 PMSep 21
to weewx-user
The AI is not "drivel" but it's also not really helpful. AI tends to keep leading you down the same incorrect path just to fulfill your instruction. SQLite3 has included a backup API since 3.3.0. There's no need to stop/start/quiesce just use the .backup command. https://www.sqlite.org/backup.html
Most of this script is error checking stuff I borrowed from my other error checking stuff. It really just boils down to:

sqlite3 /var/lib/weewx/weewx.sdb ".backup /var/tmp/weewx-$(date +%Y%m%d)-backup.sdb"

Here's the whole script nonetheless:

#!/usr/bin/env bash
set -Eeuo pipefail

# Uses SQLite Online Backup API
# Logs to journal
# View the logs with journalctl -t weewx-backup --since "1 hour ago"

#
# Add to crontab to run daily at 2 AM:
# MAILTO="f...@example.com"
# 0 2 * * * /usr/bin/env bash /usr/local/bin/weewx-backup.sh
#
DB="/var/lib/weewx/weewx.sdb"
BACKUPDIR="/var/tmp/wxbackups"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_PATH="${BACKUPDIR}/weewx-${TIMESTAMP}.sdb"
ARCHIVE_PATH="${BACKUP_PATH}.gz"

mkdir -p "$BACKUPDIR"
exec 1> >(logger -t weewx-backup) 2>&1

log() {
echo "[$(date -Is)] $*"
}

log "Starting weewx backup"

if [ ! -f "$DB" ]; then
log "ERROR: database not found: $DB"
exit 1
fi

if ! command -v sqlite3 >/dev/null 2>&1; then
log "ERROR: sqlite3 is not installed"
exit 1
fi

log "Creating SQLite backup: $BACKUP_PATH"
if ! sqlite3 "$DB" ".backup '$BACKUP_PATH'"; then
log "ERROR: SQLite backup failed"
exit 1
fi

log "Checking database integrity"
if ! sqlite3 "$BACKUP_PATH" "PRAGMA integrity_check;" | grep -qi '^ok$'; then
log "ERROR: backup integrity check failed"
rm -f "$BACKUP_PATH"
exit 1
fi

log "Compressing backup"
gzip -9 "$BACKUP_PATH"

log "Removing backups older than 30 days"
find "$BACKUPDIR" -type f -name 'weewx-*.sdb.gz' -mtime +30 -delete

log "Backup complete: $ARCHIVE_PATH"
exit 0

Warren Gill

unread,
Sep 21, 2026, 11:03:51 PMSep 21
to weewx-user
Example output from the previous script:

journalctl -t weewx-backup --since "1 hour ago"
Sep 21 22:01:49 cyclone weewx-backup[25528]: [2026-09-21T22:01:49-05:00] Starting weewx backup
Sep 21 22:01:49 cyclone weewx-backup[25528]: [2026-09-21T22:01:49-05:00] Creating SQLite backup: /var/tmp/wxbackups/weewx-20260921-220149.sdb
Sep 21 22:01:51 cyclone weewx-backup[25528]: [2026-09-21T22:01:51-05:00] Checking database integrity
Sep 21 22:01:55 cyclone weewx-backup[25528]: [2026-09-21T22:01:55-05:00] Compressing backup
Sep 21 22:02:38 cyclone weewx-backup[25528]: [2026-09-21T22:02:38-05:00] Removing backups older than 30 days
Sep 21 22:02:38 cyclone weewx-backup[25528]: [2026-09-21T22:02:38-05:00] Backup complete: /var/tmp/wxbackups/weewx-20260921-220149.sdb.gz

Pablo Sanchez

unread,
Sep 22, 2026, 6:56:09 AMSep 22
to weewx...@googlegroups.com
While I use MariaDB and create hot DB backups, for small databases like weewx, there is nothing wrong with a cold backup (where the database is stopped, backed up and started up).
---
pablo

Pablo Sanchez

unread,
Sep 22, 2026, 8:21:14 AMSep 22
to weewx...@googlegroups.com
I forgot to include that the other reason a cold back works in this Use Case is the extremely low transaction rate.

Cheers!
---
pablo

David Schulz

unread,
Sep 23, 2026, 9:13:04 PMSep 23
to weewx-user
Thanks Warren for pointing me at the backup function in SQLite itself.  At the moment I have managed to get a simple copy of the database file to a remote location working, so that is a start.  This sounds like a more fault tolerant approach as the database engine is managing both any potential writes and the backup process to void conflicts.  

My simple approach is taking seconds to execute, so judicious timing of the cron job is working for the present.

Appreciate you taking the time to chime in.  As you say, good to have someone challenging your assumptions rather than just diving deeper down the rabbit hole you're currently stuck in.

gary....@gmail.com

unread,
Sep 24, 2026, 11:22:49 AMSep 24
to weewx-user
I know there are those who treat any systemd as heresy, but I love systemd timers.

journalctl -u weewx-backup.timer -u weewx-backup.service --since "2026-09-24 00:01:55" --until "2026-09-24 00:02:15" -o short-precise
Sep 24 00:02:09.251944 weather systemd[1]: Starting weewx-backup.service - WeeWX Weather Database Backup Service...
Sep 24 00:02:09.266633 weather weewx_backup.sh[10032]: === weewx backup starting: Thu Sep 24 12:02:09 AM EDT 2026 ===
Sep 24 00:02:11.259816 weather weewx_backup.sh[10032]: === weewx backup completed: Thu Sep 24 12:02:11 AM EDT 2026 ===
Sep 24 00:02:11.265837 weather systemd[1]: weewx-backup.service: Deactivated successfully.
Sep 24 00:02:11.265970 weather systemd[1]: Finished weewx-backup.service - WeeWX Weather Database Backup Service.
Sep 24 00:02:11.266147 weather systemd[1]: weewx-backup.service: Consumed 451ms CPU time, 77.5M memory peak.

Reply all
Reply to author
Forward
0 new messages