首页 > 解决方案 > 定期运行远程备份

问题描述

我编写了一个 shell 脚本来检查远程服务器是否可访问。如果它是可访问的,它会通过 ssh 命令在不同的服务器上运行。之后,它会执行一些 rsync 任务。

一切正常,所以我写了一个 plist 文件,每 4 小时运行一次全体员工。

什么工作:

我的问题:

如果作业在 macbook 睡眠期间开始,则 ping 运行良好,但 ssh 命令不会返回。该命令在服务器上执行,但脚本在那里停止。如果我使用 ssh-command 终止该进程,则脚本会很好地完成。

我该怎么做才能获得更多信息。可能是什么错误?什么可能是另一种解决方案(Timemachine 不是一个选项,因为我想要一个通用的可读备份)?

Mac OS BigSur 11.4 M1 芯片

这是我的 plist 文件

?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
        <dict>
                <key>Label</key>
                <string>de.stanetz.backup</string>
                <key>Program</key>
                <string>/usr/local/sbin/remoteBackup.nsh</string>
                <key>RunAtLoad</key>
                <false/>
                <key>StandardOutPath</key>
                <string>/var/log/launch-stdout.log</string>
                <key>StandardErrorPath</key>
                <string>/var/log/launch-stderr.log</string>
                <key>Debug</key>
                <true/>
                <key>StartCalendarInterval</key>
                <array>
                        <dict>
                                <key>Hour</key>
                                <integer>9</integer>
                                <key>Minute</key>
                                <integer>15</integer>
                        </dict>
                </array>
                <key>ExitTimeOut</key>
                <integer>360</integer>
                <key>TimeOut</key>
                <integer>360</integer>
        </dict>
</plist>

更新:我将 ssh 命令更改为ssh -vv pooh 'echo "this runs remotely"' >/tmp/so-debug.log 2>&1. 哪个工作正常。如果我debug1: Sending command: /usr/local/sbin/handleBackupPlatte.nsh open通过 ssh 调用(运行 10 秒),则完整的 shell 脚本完成,但我在日志中发现:

debug2: channel 0: send eof
debug2: channel 0: input drain -> closed
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 2 clearing O_NONBLOCK
Killed by signal 15.

直到远程脚本完成的持续时间似乎是问题所在。

#!/bin/bash
echo "this runs remotely"
sleep 10
echo "for 10 seconds"

显示效果。但我不能让脚本更快:-/ 有什么想法,除了将 ssh 命令发送到后台?

更新2:如果mac book处于睡眠状态,似乎每个需要10秒的网络调用都会挂起并且永远不会完成。

标签: macosbackupplistlaunchd

解决方案


我改用另一种方法。我安装了 sleepwatcher,它会通知 macbook 是否被唤醒。此外,我将它与一个脚本结合使用,以确保不是在每次唤醒时备份都在运行。这里的脚本

#!/bin/bash
#set -x
set -eu


## RETURN_CODES
# 11 -> BACKUP_ALREADY_RUNNING
# 12 -> NIGHT -> No Backup
# 13 -> Last backup is too young.

#VARIABLES
LOCK_FILE="/tmp/.backup.lock"
LAST_SUCCESS_FILE="/var/log/.backup.last_success"
RUN_CONTROL="/var/log/throttle.log"
MIN_BACKUP_AGE=240

cleanup() {
        exitCode=$?
        date +"Exit Throttle at  %d.%m.%Y %H:%M:%S with $exitCode" >> ${RUN_CONTROL}    
        
        if [[ "$exitCode" -ne 11 ]]; then
                rm ${LOCK_FILE}
        fi
        echo "$(tail -n 100 ${RUN_CONTROL})" > ${RUN_CONTROL}
        
        exit $exitCode  
}

trap cleanup EXIT

test -e ${LOCK_FILE} && echo "${LOCK_FILE} exists" && exit 11
touch ${LOCK_FILE}

hour=$(date +%H)

if [ "$hour" -gt 22 ] || [ "$hour" -lt 7 ]; then
    exit 12
fi

test -e "$(find ${LAST_SUCCESS_FILE} -mmin -${MIN_BACKUP_AGE})" && exit 13 || true

/usr/local/sbin/remoteBackup.nsh
echo "$(tail ${LAST_SUCCESS_FILE})" > ${LAST_SUCCESS_FILE}
date >> ${LAST_SUCCESS_FILE}

/Library/LaunchDaemons/de.bernhard-baehr.sleepwatcher.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>de.bernhard-baehr.sleepwatcher</string>
        <key>ProgramArguments</key>
        <array>
                <string>/opt/homebrew/sbin/sleepwatcher</string>
                <string>-V</string>
                <string>-w /usr/local/sbin/throttledBackup.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
        <key>StandardOutPath</key>
        <string>/var/log/sleepwatcher-stdout.log</string>
        <key>StandardErrorPath</key>               
    <string>/var/log/sleepwatcher-stderr.log</string>
</dict>
</plist>

推荐阅读