预定的、带时间戳的 sqlite3 .backup?

Scheduled, timestamped sqlite3 .backup?

运行 pythonanywhere 上的一个小数据库,我正在尝试设置我的 sqlite3 数据库的预定 .backup。有没有办法在命令行中为文件名添加一个 time/date 标记,这样它就不会覆盖前几天的备份?

如果重要的话,这是我正在使用的代码:

sqlite3 db.sqlite3
.backup dbbackup.sqlite3
.quit

运行 每 24 小时一次。不过,前一天的备份会被覆盖。我希望能够将其保存为 dbbackup.timestamp.sqlite3 或其他格式,这样我就可以有多个可用的备份。

谢谢!

I suggest you to handle this case with management commands and cronjob.

这是一个如何做的例子;保存此文件,例如 yourapp/management/commands/dbackup.py,不要忘记添加 __init__.py 个文件。

yourapp/management/__init__.py
yourapp/management/commands/__init__.py
yourapp/management/commands/dbackup.py

但是,请先将下面这些行添加到您的 settings.py

USERNAME_SUPERUSER = 'yourname`
PASSWORD_SUPERUSER = `yourpassword`
EMAIL_SUPERUSER = `youremail@domain.com`
DATABASE_NAME = 'db.sqlite3'

部署在 pythonanywhere 的重要树路径项目;

/home/yourusername/yourproject/manage.py
/home/yourusername/yourproject/db.sqlite3
/home/yourusername/yourproject/yourproject/settings.py
/home/yourusername/yourproject/yourapp/management/commands/dbackup.py

将下面这些脚本添加到yourapp/management/commands/dbackup.py,您也可以根据需要自定义此脚本。

import os
import time
from django.conf import settings
from django.contrib.auth.models import User
from django.core.management.base import (BaseCommand, CommandError)

USERNAME_SUPERUSER = settings.USERNAME_SUPERUSER
PASSWORD_SUPERUSER = settings.PASSWORD_SUPERUSER
EMAIL_SUPERUSER = settings.EMAIL_SUPERUSER
DATABASE_NAME = settings.DATABASE_NAME #eg: 'db.sqlite3'


class Command(BaseCommand):
    help = ('Command to deploy and backup the latest database.')

    def add_arguments(self, parser):
        parser.add_argument(
            '-b', '--backup', action='store_true',
            help='Just backup command confirmation.'
        )

    def success_info(self, info):
        return self.stdout.write(self.style.SUCCESS(info))

    def error_info(self, info):
        return self.stdout.write(self.style.ERROR(info))

    def handle(self, *args, **options):
        backup = options['backup']

        if backup == False:
            return self.print_help()

        # Removing media files, if you need to remove all media files
        # os.system('rm -rf media/images/')
        # self.success_info("[+] Removed media files at `media/images/`")

        # Removing database `db.sqlite3`
        if os.path.isfile(DATABASE_NAME):
            # backup the latest database, eg to: `db.2017-02-03.sqlite3`
            backup_database = 'db.%s.sqlite3' % time.strftime('%Y-%m-%d')
            os.rename(DATABASE_NAME, backup_database)
            self.success_info("[+] Backup the database `%s` to %s" % (DATABASE_NAME, backup_database))

            # remove the latest database
            os.remove(DATABASE_NAME)
            self.success_info("[+] Removed %s" % DATABASE_NAME)

        # Removing all files migrations for `yourapp`
        def remove_migrations(path):
            exclude_files = ['__init__.py', '.gitignore']
            path = os.path.join(settings.BASE_DIR, path)

            filelist = [
                f for f in os.listdir(path)
                if f.endswith('.py')
                and f not in exclude_files
            ]
            for f in filelist:
                os.remove(path + f)
            self.success_info('[+] Removed files migrations for {}'.format(path))

        # do remove all files migrations
        remove_migrations('yourapp/migrations/')

        # Removing all `.pyc` files
        os.system('find . -name *.pyc -delete')
        self.success_info('[+] Removed all *.pyc files.')

        # Creating database migrations
        # These commands should re-generate the new database, eg: `db.sqlite3`
        os.system('python manage.py makemigrations')
        os.system('python manage.py migrate')
        self.success_info('[+] Created database migrations.')

        # Creating a superuser
        user = User.objects.create_superuser(
            username=USERNAME_SUPERUSER,
            password=PASSWORD_SUPERUSER,
            email=EMAIL_SUPERUSER
        )
        user.save()
        self.success_info('[+] Created a superuser for `{}`'.format(USERNAME_SUPERUSER))

使用 crontab 设置此命令

$ sudo crontab -e

并在下面添加以下内容;

# [minute] [hour] [date] [month] [year]
59 23 * * * source ~/path/to/yourenv/bin/activate && cd ~/path/to/yourenv/yourproject/ && ./manage.py dbackup -b

但是,如果需要部署在pythonanywhere,只需要加上这些..

每天 [hour][minute] UTC,...填写 hour=23minute=59

source /home/yourusername/.virtualenvs/yourenv/bin/activate && cd /home/yourusername/yourproject/ && ./manage.py dbackup -b

更新 1

I suggest you to update the commands to execute the file of manage.py such as os.system('python manage.py makemigrations') with function of call_command;

from django.core.management import call_command
call_command('collectstatic', verbosity=3, interactive=False)
call_command('migrate', 'myapp', verbosity=3, interactive=False)

...等同于在终端中输入以下命令:

$ ./manage.py collectstatic --noinput -v 3
$ ./manage.py migrate myapp --noinput -v 3

参见 running management commands from django docs

更新 2

之前的条件是您是否需要 re-deploy 您的项目并使用新的数据库。 但是,如果你只想通过重命名数据库来备份它,你可以使用shutil.copyfile

的模块
import os
import time
import shutil
from django.conf import settings
from django.core.management.base import (BaseCommand, CommandError)

DATABASE_NAME = settings.DATABASE_NAME #eg: 'db.sqlite3'


class Command(BaseCommand):
    help = ('Command to deploy and backup the latest database.')

    def add_arguments(self, parser):
        parser.add_argument(
            '-b', '--backup', action='store_true',
            help='Just backup command confirmation.'
        )

    def success_info(self, info):
        return self.stdout.write(self.style.SUCCESS(info))

    def error_info(self, info):
        return self.stdout.write(self.style.ERROR(info))

    def handle(self, *args, **options):
        backup = options['backup']

        if backup == False:
            return self.print_help()

        if os.path.isfile(DATABASE_NAME):
            # backup the latest database, eg to: `db.2017-02-29.sqlite3`
            backup_database = 'db.%s.sqlite3' % time.strftime('%Y-%m-%d')
            shutil.copyfile(DATABASE_NAME, backup_database)
            self.success_info("[+] Backup the database `%s` to %s" % (DATABASE_NAME, backup_database))