heimi DD-WRT Novice
Joined: 06 Dec 2012 Posts: 2
|
Posted: Thu May 01, 2014 11:44 Post subject: nvrambak.bin cron backup and python decoder |
|
Hi,
I'd liked automatic backups by nvram backup which is possible in newer firmware. This command is called by ssh, cat in a local file which is compared with yesterdays file and kept if it differs. Oneliner for use in a cron.
Code: |
umask 077;E=nvram;H=ddwrt;D=/var/backups/${H}_bak;A=${D}_$(date +\%F).${E};ssh $H 'B=/tmp/backup.nvram; nvram backup $B; cat $B; rm $B' 2>/dev/null >$A;B=${D}_$(date -d yesterday +\%F).${E}; if [ -f $B ]; then diff -q $A $B >/dev/null && rm $B; fi; exit 0
|
Remarks: cat, the output redirect and diff are working on binary files, but that's ok...
But, I'd like to track changes so I needed the textual representation of the backup. I could have used nvram show instead, but this cannot be used for restore and has problems with multiline values, so I ended up with the Python script below.
The ASCII output can easily be sorted (breaks multiline values) and than diffed with another dump for a quick overview of changes.
Code: |
#!/usr/bin/env python
import struct
import os, sys, mmap
class NVRam(object):
def __init__(self, filename, use_mmap=True):
nvram_file = open(filename)
if use_mmap:
nvram_size = os.path.getsize(filename)
self.data = mmap.mmap(nvram_file.fileno(), nvram_size, access=mmap.ACCESS_READ)
else:
self.data = nvram_file.read()
#print('Read: ' + str(nvram_size));
self.iter_position = 6
header = self.data[0:self.iter_position]
assert(header == 'DD-WRT')
self.iter_position += 2
while self.iter_position < nvram_size:
key = self.readKey()
value = self.readValue()
print(key + '=' + value)
def readValue(self):
len = self.readWord()
if len == 0:
return ''
start = self.iter_position
self.iter_position += len
return self.data[start:self.iter_position]
def readKey(self):
len = self.readByte();
start = self.iter_position
self.iter_position += len
return self.data[start:self.iter_position]
def readWord(self):
start = self.iter_position
self.iter_position += 2
subset = self.data[start:self.iter_position]
return struct.unpack('H', subset)[0]
def readByte(self):
start = self.iter_position
self.iter_position += 1
subset = self.data[start:self.iter_position]
return struct.unpack('B', subset)[0]
def main():
if len(sys.argv) != 2:
print('Give DDWrt nvram file as first param.');
exit(1)
nvram = NVRam(sys.argv[1])
if __name__ == '__main__':
main()
|
|
|