Ecrose's Blog

🏠HOME 📑POSTS 👀MESSAGE 🔗LINK 🖇️RSS
https://cdn.jsdelivr.net/gh/2cracer2/oss@master/uPic/server_backup.jpg

vps服务器自动备份实践

2024-03-02 20:32

  • 杂技浅尝
  • 数据备份

国内云厂商

以腾讯云为例可以结合云函数调用服务器提供商的快照 api 实现定期自动备份。

其他 VPS

前者不一定所有厂商都有,而且不一定免费。具体使用 restic + rclone 来备份(Rclone 支持在不同对象存储、网盘间同步、上传、下载,且支持增量备份;而 Restic 是文件加密,增量备份工具,并且支持快照,并且备份与恢复策略都可灵活配置)。

可以结合使用,利用 Rclone 访问广泛的存储后端和 Restic 的加密及去重备份功能。

Rclone

安装 Rclone

  • Rclone 也可以从大多数 Linux 发行版的官方仓库安装。例如,在基于 Debian 的系统上,使用:
sudo apt-get update
sudo apt-get install rclone

对于 macos

brew install rclone

配置 Rclone

Rclone 支持多种云存储服务,包括但不限于 Amazon S 3, Google Drive, Dropbox, OneDrive 等。它能够处理文件同步、文件传输以及数据备份任务。 同时配置好的 Rclone 进行迁移也很方便,只要配置一次后,可以在不同的服务器上迁移,只要将配置文件 rclone.conf 进行复制迁移到配置文件夹中就行。 通过 rclone config file 查看配置文件夹位置。

Rclone 连接 OneDrive

更多其他的云存储、云盘挂载见 rclone 文档。

为了在不同服务器间迁移配置,OneDrive 挂载方式推荐通过 webdav,而不是 api。

  1. 启动 Rclone 配置向导:
    • 输入 rclone config。这将启动 Rclone 的配置向导。
    • 创建新的远程存储配置,选择 n 新建配置。
  2. 命名远程存储:
    • 向导接下来会询问为这个远程存储配置起一个名字为 xx_onedrive
  3. 选择存储类型:
    • 向导会展示出支持的存储类型列表。对于通过 WebDAV 挂载 OneDrive,需要找到并选择 WebDAV(注意,这个列表可能会随 Rclone 版本更新而变化)。
  4. 配置 WebDAV 参数:
    • URL:接下来,向导会要求输入 WebDAV 服务器的 URL。OneDrive 的 WebDAV 地址通常形式 https://xxxxxxxcn-my.sharepoint.com/personal/YOUR_ONEDRIVE_USERID/Documents。这里 YOUR_ONEDRIVE_USERID 需要替换成你的 OneDrive 用户 ID。
    • # Choose a number from below, or type in your own value# 选择 3 / Sharepoint
    • 然后输入 email 账号和密码
    • bearer_token 默认留空

配置完成后通过 rclone ls xx_onedrive: 查看是否正常连接。 Rclone 在配置文件中保存密码时,使用的是 NaCl (Networking and Cryptography library) 的加密库进行加密,但仍需要保管好 rclone.conf 文件。 如果你的系统支持 FUSE,还可以将 OneDrive 通过 WebDAV 挂载到本地文件系统:

rclone mount xx_onedrive:/ /path/to/mountpoint --daemon

使用 Rclone

虽然 Rclone 也支持增量加密备份,但是不支持快照和版本管理。 所以需要增量备份,版本管理的文件,用 Resitc 就比较合适,把 Rclone 作为 Resitc 的后端;而常规文件的远程备份归档,或者多个云存储服务之间迁移数据,直接用 Rclone 就很合适。

常规文件的远程备份归档

这里以 /home/user/data 为例。使用 tar 命令来压缩这个文件夹:

tar -czvf data_backup.tar.gz /home/user/data

使用 gpg 对压缩文件进行对称加密,这里建议使用强加密算法如 AES 256。(虽然 Rclone 也支持在远端指定创建加密文件夹)

gpg --symmetric --cipher-algo AES256 data_backup.tar.gz

执行此命令后,系统会提示输入密码,用于加密文件。这会生成一个名为 data_backup.tar.gz.gpg 的加密文件。 在上传文件之前,确保已经设置好了指向 OneDrive 的 Rclone 远程配置,使用 Rclone 在 OneDrive 上创建指定存放备份的文件夹,比如 normal_backup :

rclone mkdir xx_onedrive:/normal_backup

上传

rclone copy data_backup.tar.gz.gpg xx_onedrive:/normal_backup

不同的云存储服务之间迁移

使用 Rclone 的 copy 或 sync 命令来迁移数据。copy 命令会将源位置的文件复制到目标位置,而 sync 命令会同步源位置和目标位置的内容,使目标位置的内容与源位置完全一致,包括删除目标位置上在源位置不存在的文件。

使用 copy 迁移数据(不会删除目标中多余的文件):

rclone copy onedrive:Photos gdrive:PhotosBackup

这个命令会将 OneDrive 中 Photos 文件夹的内容复制到 Google Drive 中的 PhotosBackup 文件夹。如果 PhotosBackup 文件夹不存在,Rclone 会自动创建。 使用 sync 迁移数据(使目标与源同步,包括删除操作):

rclone sync onedrive:Photos gdrive:PhotosBackup

这个命令会同步 OneDrive 中 Photos 文件夹的内容到 Google Drive 中的 PhotosBackup 文件夹,使 PhotosBackup 中的内容与 Photos 完全一致。

简单对云存储管理

增加(上传)文件(及过滤规则使用)

已经介绍了的增加(上传)文件,再介绍一些过滤规则使用。

rclone copy / remote:backup --dry-run \
  --include "/root/**" --include "/home/**" \
  --exclude "/root/.*" \
  --exclude "/home/code/**" --exclude "/home/config/test/**"

在这个命令中:

  • copy / remote:backup 表示将根目录(/)下的内容复制到远程存储的 backup 目录。实际上传的内容将受到下面定义的包含和排除规则的影响。
  • --include "/root/**" 和 --include "/home/**" 表示包含 /root 和 /home 目录及其所有子目录和文件。
  • --exclude "/root/.*" 排除了 /root 目录下所有以点(.)开头的文件和文件夹。
  • --exclude "/home/code/**" 和 --exclude "/home/config/test/**" 分别排除了 /home/code 和 /home/config/test 目录及其所有子目录和文件
删除文件

删除远程存储中的单个文件: 使用 deletefile 命令删除指定的单个文件。

rclone deletefile remote:path/to/file -i

删除远程存储中的整个文件夹: 使用 purge 命令删除整个文件夹及其内容。

rclone purge remote:path/to/folder -i

使用 --dry-run 或 -i(交互模式)选项可以预览将要执行的操作,而不实际执行,避免误删除。

修改文件

rclone 并不直接支持修改远程存储中的文件内容(例如,编辑文件)。修改通常涉及下载文件,进行本地编辑,然后重新上传覆盖原文件。但有移动操作 move, 移动操作会将源文件或文件夹删除,仅在目标位置保留副本。

rclone move source:path/to/file_or_folder dest:path/to/dest_folder

rclone move /path/to/local/file_or_folder remote:path/to/dest #从本地移动到远程存储

rclone move remote:path/to/source/file_or_folder remote:path/to/dest #在远程存储内移动
查看文件和文件夹

列出远程文件夹的内容: 使用 ls 命令列出远程文件夹中的文件。

rclone ls remote:path/to/folder

递归列出文件夹及其子文件夹的内容: 使用 lsf 命令以递归方式列出文件夹及其所有子文件夹的内容,可以使用 -R 选项。

rclone lsf -R remote:path/to/folder

查看文件详情: 使用 lsd 命令列出远程文件夹的详细信息,包括子文件夹。

rclone lsd remote:path/to/folder

关键词查询只能用管道符: rclone lsf remote:path/to/folder | grep "keyword"

Rclone 性能优化

调整并行传输数 --transfers

Rclone 默认同时运行四个文件传输。在带宽允许的情况下,增加 --transfers 参数的值可以显著提高传输速度,特别是在传输大量小文件时。例如,将并行传输数增加到 10:

export RCLONE_TRANSFERS=10

或者

rclone copy /path/to/source remote:destination --transfers 10

调整检查者数量 --checkers

Rclone 使用检查者来检查文件是否需要传输。增加检查者的数量可以加快这一过程,尤其是在有大量文件需要检查时。例如,将检查者数量增加到 20:

rclone sync /path/to/source remote:destination --checkers 20

Restic

Restic 主要特性包括:

  • 去重: Restic 在备份数据时采用去重技术。它将数据分割成小块,并对每块进行哈希处理。如果数据块的内容已经存在于备份仓库中,则不会再次存储,从而有效减少了存储空间的需求。
  • 加密: Restic 默认对所有备份数据进行端到端加密。它在数据离开本地机器之前就进行加密,确保了数据的安全性。
  • 快照: Restic 以快照的形式存储备份。每次备份都是一个完整的快照,但由于去重技术的使用,每个新快照只增加了自上次备份以来变化的数据量。 具体介绍见文档

安装 Restic

大多数 Linux 发行版都可以通过包管理器安装 Restic。例如,在基于 Debian 的系统上,可以使用:

sudo apt install restic

macOS:

brew install restic

配置 Restic

初始化备份仓库: 首先,需要初始化一个备份仓库,这可以是本地目录、远程服务器或任何 Restic 支持的后端存储。 初始化需输入两次密码例如,初始化一个本地仓库:

restic init --repo /path/to/restic-repo

结合已经配置好的 Rclone 初始化 Restic 仓库:

  • 使用 rclone 作为后端,初始化 Restic 仓库:
restic -r rclone:OneDrive/backup init

使用 Restic

创建备份

restic -r rclone:OneDrive:backup backup /path/to/your/data

日常使用时常结合多个过滤需求

restic -r rclone:OneDrive:backup backup /root /home \
  --exclude '/root/.*' \
  --exclude '/home/code' \
  --exclude '/home/config/test'

也可由文件读取对应参数,见后面的脚本示例。

同时为了方便管理和识别不同的备份,可在备份时创建添加标签(--tag)或指定主机名(--host)

  • 使用标签:
restic -r rclone:OneDrive:backup backup /path/to/data --tag mytag
  • 使用主机名:
restic -r rclone:OneDrive:backup backup /path/to/data --host myhost

查看备份

要列出所有的备份快照,可以使用 restic snapshots 命令:

restic -r rclone:OneDrive:backup snapshots

查看特定快照的详细信息 可以查看某个特定快照的更详细信息,包括快照中包含的文件和目录结构。使用 restic ls 命令加上快照 ID 来实现:

restic -r rclone:OneDrive:backup ls <snapshot-id>
使用标签、主机名和时间过滤快照
  • 按标签过滤:
restic -r rclone:OneDrive:backup snapshots --tag <tag-name>
  • 按主机名过滤:
restic -r rclone:OneDrive:backup snapshots --host <host-name>
  • 按时间过滤:
restic -r rclone:OneDrive:backup snapshots --last 24h
  • 查看快照之间的差异:

Restic 还提供了一个强大的功能,允许比较两个快照之间的差异,看看在两次备份之间哪些文件被改变、添加或删除:

restic -r rclone:OneDrive:backup diff <snapshot-id1> <snapshot-id2>
Restic 仓库挂载为一个文件系统

restic mount 命令允许将 Restic 仓库挂载为一个文件系统,这样用户就可以使用标准的文件浏览器或命令行工具来访问备份数据。这是通过使用 FUSE (Filesystem in Userspace) 技术实现的,它允许创建一个用户空间的文件系统。

restic -r /path/to/repository mount /path/to/mountpoint

管理备份

随着时间的推移,备份快照可能会占用大量存储空间。使用 restic forget 命令可以删除不再需要的旧快照。结合 restic prune 命令,可以进一步清理未被任何快照引用的数据,释放存储空间。注意使用 --dry-run 选项进行模拟操作

# 删除快照列表信息
$ restic -r rclone:OneDrive:backup snapshots
$ restic -r rclone:OneDrive:backup forget 6eda7c7d

# 清除未引用的数据
# 快照中文件引用的数据仍然存储在存储库中
$ restic -r rclone:OneDrive:backup prune
restic -r rclone:OneDrive:backup forget --keep-last 10 --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --keep-yearly 3 --dry-run

这个命令会根据保留策略删除一些旧快照,例如,仅保留最近 10 个快照、每天一个快照保留 7 天等。

恢复快照

恢复备份快照是 Restic 最重要的功能之一。除了基本的恢复操作外,Restic 还提供了一些高级实用操作,使得从备份中恢复数据更加灵活和高效。


restic -r rclone:OneDrive:backup snapshots --time "2024-02-25"

# 只需使用以下命令就可以将最新快照的内容恢复
$ restic -r rclone:OneDrive:backup \
    restore 79766175 --target /tmp/restore-work
恢复特定文件或目录

如果只需要从快照中恢复特定的文件或目录,而不是整个快照,可以使用 --include 或 --exclude 选项来指定恢复范围。

restic -r rclone:OneDrive:backup restore <snapshot-id> --target /path/to/restore --include "/path/to/file.txt"

restic -r rclone:OneDrive:backup restore <snapshot-id> --target /path/to/restore --include "/path/to/large_directory/" --exclude "/path/to/large_directory/exclude_this_subdir"
恢复备份时的安全检查

当使用 restic restore 命令恢复数据时,添加 --verify 选项将指示 Restic 在恢复每个文件后立即对其内容进行校验。这意味着 Restic 会比较文件的内容哈希值与仓库中记录的哈希值,以确保它们完全匹配。

restic -r rclone:OneDrive:backup restore <snapshot-id> --target /path/to/restore --verify

常见异常处理

锁定机制

Restic 使用锁定机制来确保备份仓库的数据一致性和完整性。在进行备份、恢复或维护操作时,Restic 会在备份仓库中创建一个特殊的锁文件。这个锁文件包含了操作的类型、开始时间以及操作者的信息。如果存在一个活动锁,Restic 会阻止其他可能会影响数据一致性的操作执行,直到该锁被释放。

  • 独占锁: 用于备份和修剪操作,确保在这些操作执行期间,没有其他操作可以修改仓库数据。
  • 共享锁: 允许多个读取操作同时进行,例如列出快照或检查仓库,但阻止写入操作。

在命令行中使用 Restic 时,锁定机制是自动管理的。用户不需要手动创建或释放锁。但是,如果操作被非正常终止(如进程崩溃或网络断开),可能会留下孤立的锁文件。Restic 提供了 unlock 命令来清理这些孤立的锁:

restic -r /path/to/repository unlock

实践结合 Restic 与 Rclone 自动备份及备份状态推送

步骤 1: 创建配置文件

创建一个配置文件 backup_config.conf,在其中定义备份仓库、密码文件、备份路径、排除规则文件以及日志文件路径。例如放置于 /usr/local/bin/restic_backup

# backup_config.conf

# The repository location for restic backups. This is specified using the rclone backend syntax.
# Format: "rclone:<rclone remote name>:<path within the remote>"
RESTIC_REPOSITORY="rclone:OneDrive:backup"

# Path to the file containing the password for the restic repository. 
# This file should be secured with appropriate permissions to prevent unauthorized access.

PASSWORD_FILE="/usr/local/bin/restic_backup/restic_password_file"

# File containing a list of paths to include in the backup. Each path should be on a separate line.

# File containing patterns to exclude from the backup. Each pattern should be on a separate line.
EXCLUDE_FILE="/usr/local/bin/restic_backup/exclude_rules.txt"

# Path to the log file where backup operation details will be recorded.
LOG_FILE="/var/log/restic_backup.log"

# A tag to assign to all snapshots created by this backup for easy identification and management.
BACKUP_TAG="automated_backup"

# The number of most recent snapshots to keep. Older snapshots exceeding this count will be pruned.
KEEP_SNAPSHOTS=5  # Number of snapshots to retain

# Rclone performance optimization settings
# The number of file transfers to run in parallel. Increasing this can improve transfer speeds,
# especially for a large number of small files, assuming the bandwidth allows for it.
# The default in rclone is 4 parallel transfers.
RCLONE_TRANSFERS=10

# The number of checkers to use. Checkers are used by rclone to determine if a file needs to be transferred.
# Increasing this number can speed up this checking process, which can be beneficial when dealing with
# a large number of files. This setting helps in speeding up the comparison between source and destination.
RCLONE_CHECKERS=20


# Telegram notification settings
# TELEGRAM_TOKEN: The API token of your Telegram bot. Leave this empty if you do not wish to send Telegram notifications.
# TELEGRAM_CHAT_ID: The chat ID where notifications will be sent. This can be a personal chat ID or a group chat ID.
# Leave these empty to disable Telegram notifications.
TELEGRAM_TOKEN="1111111223:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
TELEGRAM_CHAT_ID="123433545"

创建密码文件注意路径与 PASSWORD_FILE 参数对应 可适当修改RCLONE_TRANSFERS和RCLONE_CHECKERS参数可提高在备份大量小文件时的性能。 以及添加Telegram消息推送备份结果

步骤 2: 创建相关文件

创建密码文件:

echo "your_restic_password" > /usr/local/bin/restic_backup/restic_password_file
# 设置文件权限
chmod 600 /usr/local/bin/restic_backup/restic_password_file

创建备份路径文件:

/home
/root

创建排除规则文件: 创建一个排除规则文件 exclude_rules.txt,在其中列出所有要排除的文件夹和文件类型。注意路径与 EXCLUDE_FILE 文件对应。

# exclude_rules.txt
/home/user/documents/temp
/home/user/photos/drafts
*.tmp
*.cache

# 排除所有以点开头的隐藏文件和文件夹
.*

# 但保留特定的文件,如 .zshrc
!.zshrc

步骤 3: 编写备份脚本及清理脚本

编写一个新的备份脚本 restic_backup.sh,使用配置文件,实现日志记录以及错误处理和重试机制,并在脚本结束时提供备份摘要和推送备份结果。

#!/bin/bash

source /usr/local/bin/restic_backup/backup_config.conf

# Check for required commands
for cmd in restic curl hostname; do
    if ! command -v $cmd &> /dev/null; then
        echo "Error: Required command '$cmd' not found. Exiting."
        exit 1
    fi
done

export RCLONE_TRANSFERS=$RCLONE_TRANSFERS
export RCLONE_CHECKERS=$RCLONE_CHECKERS

backup_success=true

# Function to send Telegram notification
send_telegram() {
    local message=$1
    if [[ -z "$TELEGRAM_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then
        echo "Telegram token or chat ID not set. Skipping notification."
        return 1
    fi
    if ! curl -s -X POST https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage -d chat_id=$TELEGRAM_CHAT_ID -d text="$message" > /dev/null; then
        echo "Warning: Failed to send Telegram notification."
    fi
}

# Backup function with retry logic
backup() {
    local retries=2
    local delay=10  # Initial retry delay in seconds
    local attempt=0

    while [ $attempt -le $retries ]; do
        local start_time=$(date +%s)
        echo "Starting backup at $start_time, attempt $((attempt+1))" >> "$LOG_FILE"

        if restic -r "$RESTIC_REPOSITORY" --password-file "$PASSWORD_FILE" backup --files-from "$FILES_FROM" --exclude-file="$EXCLUDE_FILE" --tag "$BACKUP_TAG" >> "$LOG_FILE" 2>&1; then
            local end_time=$(date +%s)
            echo "Backup completed successfully at $end_time. Duration: $((end_time - start_time)) seconds." >> "$LOG_FILE"
            return 0
        else
            local end_time=$(date +%s)
            echo "Backup failed, attempt $((attempt+1)) at $end_time. Check log $LOG_FILE for details." >> "$LOG_FILE"
            attempt=$((attempt + 1))
            sleep $delay
            delay=$((delay * 2))  # Exponential backoff
        fi
    done

    echo "Backup failed after $retries retries at $(date +%Y-%m-%d\ %H:%M:%S)." >> "$LOG_FILE"
    backup_success=false
}


# Retrieve hostname and IP address
HOSTNAME=$(hostname)
IP_ADDRESS=$(curl -s ip.sb)

# Function to summarize backup operation and send Telegram notification
backup_summary() {
    local end_time=$(date +"%Y-%m-%d %H:%M:%S")
    if $backup_success; then
        local stats_output=$(restic -r "$RESTIC_REPOSITORY" --password-file "$PASSWORD_FILE" stats | awk '/Stats in restore-size mode:/,0')
        echo "All backups completed successfully at $end_time" >> "$LOG_FILE"
        send_telegram "🎉 Backup completed successfully at $end_time 🎉
🖥️ Hostname: $HOSTNAME
🌐 IP Address: $IP_ADDRESS
💾 Repository: $RESTIC_REPOSITORY
🤖 Repository Stats: 

$stats_output"
    else
        echo "One or more backups failed at $end_time, see log $LOG_FILE for details." >> "$LOG_FILE"
        send_telegram "❌ Backup failed at $end_time ❌
🖥️ Hostname: $HOSTNAME
🌐 IP Address: $IP_ADDRESS
💾 Repository: $RESTIC_REPOSITORY
Check log $LOG_FILE for details."
    fi
}

echo "Starting backup process at $(date +"%Y-%m-%d %H:%M:%S")" >> "$LOG_FILE"

backup

if ! $backup_success; then
    echo "Performing detailed check due to previous failures..." >> "$LOG_FILE"
    restic -r "$RESTIC_REPOSITORY" --password-file "$PASSWORD_FILE" check >> "$LOG_FILE" 2>&1
    send_telegram "Restic repository check performed due to backup failure. Check log $LOG_FILE for details."
else
    echo "Skipping detailed check as all backups were successful." >> "$LOG_FILE"
fi

backup_summary

赋予脚本执行权限:chmod +x /path/to/restic_backup.sh。

编写清理快照脚本,具体要保留的快照数量可以在配置文件中自行修改,注意具有不同的路径或标签,它们被视为不同的备份集合,会单独计算保存的快照数量。

#!/bin/bash

source /usr/local/bin/restic_backup/backup_config.conf


HOSTNAME=$(hostname)
IP_ADDRESS=$(curl -s ip.sb)


send_telegram() {
    local message=$1
    if [[ -z "$TELEGRAM_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then
        echo "Telegram token or chat ID not set. Skipping notification."
        return 1
    fi
    if ! curl -s -X POST https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage -d chat_id=$TELEGRAM_CHAT_ID -d text="$message" > /dev/null; then
        echo "Warning: Failed to send Telegram notification."
    fi
}

cleanup_snapshots() {
    echo "Starting cleanup process at $(date +"%Y-%m-%d %H:%M:%S")" >> "$LOG_FILE"
    
    if restic -r "$RESTIC_REPOSITORY" --password-file "$PASSWORD_FILE" forget --keep-last "$KEEP_SNAPSHOTS" --prune 2>>"$LOG_FILE"; then
        local stats_output=$(restic -r "$RESTIC_REPOSITORY" --password-file "$PASSWORD_FILE" stats | awk '/Stats in restore-size mode:/,0')
        echo "Cleanup completed successfully at $(date +"%Y-%m-%d %H:%M:%S"). Kept the last $KEEP_SNAPSHOTS snapshots." >> "$LOG_FILE"
        send_telegram "🧹 Cleanup completed successfully at $(date +"%Y-%m-%d %H:%M:%S").
🖥️ Hostname: $HOSTNAME
🌐 IP Address: $IP_ADDRESS
💾 Repository: $RESTIC_REPOSITORY
Kept the last $KEEP_SNAPSHOTS snapshots.
🤖 Repository Stats: 

$stats_output"
    else
        echo "Cleanup failed at $(date +"%Y-%m-%d %H:%M:%S"), see log for details." >> "$LOG_FILE"
        send_telegram "❌ Cleanup failed at $(date +"%Y-%m-%d %H:%M:%S").
🖥️ Hostname: $HOSTNAME
🌐 IP Address: $IP_ADDRESS
💾 Repository: $RESTIC_REPOSITORY
Check log $LOG_FILE for details."
    fi
}

cleanup_snapshots

赋予脚本执行权限:chmod +x /path/to/restic_cleanup.sh。

步骤 4: 配置定时任务

crontab -e

在编辑器中,添加一行以定义新的计划任务。以下是一些常见的时间设置示例:

# 每个月的第二天的凌晨 2 点 1 分执行

0 2 1 * * /bin/bash /path/to/your_backup_script.sh >> /path/to/backup_cron.log 2>&1

# 每3个月执行一次清理
0 2 1 */3 * /bin/bash /path/to/restic_cleanup.sh >> /path/to/cleanup_cron.log 2>&1

运行 crontab -l 来列出所有已经安排的 cron 作业,确保的备份任务已经被正确添加。

Port Knocking 端口敲门✊

2024-03-01 00:45

Ecrose

Ecrose

尽心尽力,自有万里长风。

Related Posts

  • Port Knocking 端口敲门✊
  • DALLE 教程
  • mac-mini 折腾
  • 数据备份方案
  • 命令行的艺术

Categories

  • 杂技浅尝 8
  • 技术 2
  • 数据库 1
  • 杂七杂八 1

Tags

资源 Database 工具使用 数据备份 安全 日常 隐写术

© 2022 Ecrose.

Powered by Hugo Theme - kagome

🌞 light 🌛 dark 🤖️ auto