I wrote this script to do an incremental backup of my running system.  Use 
at your own risk.

This script reads the weewx.sdb tables and insert/updates
records in a backup database.  It gets the last datetime from each of the 
weewx archive*
tables.  For the archive table, it inserts any new records in the backup
database.  For the archive_day_* tables, it deletes the last record in the  
backup database and then inserts any new records.
The exception is the archive_day__metadata table.  It is not touched.

I copied the weewx.sdb file to weewxCopy.sdb and then run the following to 
backup the database.  

zkwx_incrementCopy.py -f PATH_TO/weewx.sdb -t PATH_TO/weewxCopy.sdb

Good Luck,
Oscar

On Sunday, December 25, 2016 at 2:55:39 AM UTC-7, Per Edström wrote:
>
> I run my Weewx on Raspberry Pi and on a  "PC" (Ebox 3350 and Ubuntu 10). 
> Both have the OS on an SD/SDHC-card.
>
> Now, I find it messy to create a backup image:
> 1. Halt system
> 2. Power down
> 3. Remove SD-card
> 4. Put in laptop and create an image to file (5-10 min)
> 5. Insert SD-card in taget again and power up.
> 6. Write image file to new SD-card (15-20 min).
>
> (NB! I have noted that not all 16GB SD-card have the exact same size, it 
> varies quite a lot. This became an issue the trying to find a new SD-card 
> for the one that failed..)
>
> This procedure takes time and requires quite a lot of physical 
> intervention.
>
> Is there any way of to create or maintain an updated image from the 
> running system. Maybe it's Ok to just backup some files (user installed)?
>
> Also, it would be nice to have this "backup SD" as an alternative boot 
> SD-card in case the primary one fails. I don't know if that is possible..
>

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
#!/usr/bin/python
################################################################################
# Filename:  zk_wx_incrementCopy.py
# Description:  This script eads the weewx.sdb tables and insert/updates
#   records in a backup database.  It gets the last datetime from the archive*
#   tables.  For the archive table, it inserts any new records in the backup
#   database.  For the archive_day_* tables, it deletes the last record in the
#   backup database and then inserts any new records.  It does not copy the
#   archive_day__metadata table.
#
###
# Date        Author    Comment 
# 2016-12-16  obarlow   Create initial script
################################################################################
# IMPORT libraries
import datetime
import getopt
import os.path
import sqlite3
import sys
################################################################################
# define Variables
################################################################################
debugLevel = 1
################################################################################
# Connect to a data base
################################################################################
def connect_db( sqliteDB, readOnly ):
    connection = None
    try:
        if readOnly == True:
#            connection = sqlite3.connect(sqliteDB + '?mode=ro')
            connection = sqlite3.connect(sqliteDB)
        else:
            connection = sqlite3.connect(sqliteDB)

        return connection        
    except sqlite3.Error, e:
        print "Error opening DB %s:" % sqliteDB
        print "Error %s:" % e.args[0]
        sys.exit(1)     

################################################################################
# Execute sql
################################################################################
def execute_sql( connection, sqliteSQL ):
    try:
        cursor = connection.cursor()        
        cursor.execute(sqliteSQL)               
        
        return cursor
    except sqlite3.Error, e:
        print "Error SQL %s:" % sqliteSQL
        print "Error %s:" % e.args[0]
        sys.exit(1)     
################################################################################
# getStartTime
################################################################################
def getStartTime(i_archiveCon ):

    
    SQL = 'SELECT min(dateTime) minTime from archive'
    
    wvArchiveCur = execute_sql( i_archiveCon, SQL )

    wvArchiveRow = wvArchiveCur.fetchone()
    
    return wvArchiveRow[0]
    
################################################################################
# get parameters
################################################################################
try:
   opts, args = getopt.getopt(sys.argv[1:],"f:t:")
except getopt.GetoptError:
   print 'no parms'
   sys.exit(2)

if opts:
    for opt, arg in opts:
        if opt == '-f':
            sourceDB = arg
        elif opt == '-t':
            targetDB = arg
        
        else:
            print "Unknown Parm:" + opt
            sys.exit(2)

    fromError = False
    toError = False
    
    if os.path.isfile(sourceDB):
        a = 1
    else:
        fromError = True
       
    if os.path.isfile(targetDB):
        a = 1
    else:
        toError = True
       
    if fromError or toError:
        if fromError:
            print "From database not found: " + sourceDB
       
        if toError:
            print "To database not found: " + targetDB
       
        sys.exit(2)
################################################################################
# Main Process starts here
################################################################################
try:

    commitCounter = 0;
    commitMax = 100;
    
    sourceCon = connect_db( sourceDB, True )
    targetCon = connect_db( targetDB, False )

    tableSQL = "SELECT name FROM sqlite_master WHERE type = 'table'"
    tableSQL = tableSQL + " and name NOT IN ('archive_day__metadata', 'reportDate')";       
    tableCur = execute_sql ( sourceCon, tableSQL )        
    tableList = tableCur.fetchall()
    
    for wvTable in tableList:
        dateColumn = 'dateTime'

        myTable = wvTable[0]
        if debugLevel > 0:
            print "Table=" + myTable,

        # this is not executed because the table is excluded from the list
        if myTable == 'archive_day__metadata':
            mySQL = "delete from archive_day__metadata"
            targetCon.execute ( mySQL )
            dataSQL = "SELECT * FROM " + myTable

        elif myTable == 'archive':
            mySQL = "SELECT max(" + dateColumn + ") from " + myTable
            myCur = execute_sql ( targetCon, mySQL )
            startDateTime = myCur.fetchone()

            dataSQL = "SELECT * FROM " + myTable + " WHERE " + dateColumn + " > " + str(startDateTime[0])
        else: 
            mySQL = "SELECT max(" + dateColumn + ") from " + myTable
            myCur = execute_sql ( targetCon, mySQL )
            startDateTime = myCur.fetchone()

            mySQL = "delete from " + myTable + " WHERE " + dateColumn + " >= " + str(startDateTime[0])
            myCur = execute_sql ( targetCon, mySQL )

            dataSQL = "SELECT * FROM " + myTable + " WHERE " + dateColumn + " >= " + str(startDateTime[0])

        rowCounter = 0
        dataCur = execute_sql ( sourceCon, dataSQL )
        rows = dataCur.fetchall()

        for row in rows:
            insertSQL = "INSERT INTO " + myTable + " VALUES ("
            for i in range(len(row)):
                if i == 0:
                   myComma = ''

                   if myTable != 'metainfo':
                       myDateTime = str(row[i])
                else:
                    myComma = ','

                insertSQL = insertSQL + myComma + "'" + str(row[i]) + "'" 

            insertSQL = insertSQL + ")" 

            if debugLevel > 4:
                print "SQL=" + insertSQL

            targetCon.execute ( insertSQL )

            commitCounter = commitCounter + 1
            rowCounter = rowCounter + 1

            if commitCounter >= commitMax:
                targetCon.commit()
                commitCounter = 0
                

        # end for row in rows
        
        targetCon.commit()
        if debugLevel > 0:
            print "Rows=" + str(rowCounter)

    
    # end for wvTable in tableList
    
    sourceCon.close()
    targetCon.close()
    
    # end of wviewDB in dbList
except sqlite3.Error, e:
#     print "Error processing %s:" % sourceDB
#     print "SQL=" + mySQL
     print "Error %s:" % e.args[0]
     print "dateTime=" + myDateTime
     sys.exit(1)     
        

Reply via email to