¿Cómo volver a abarcar un script launchd similar a cron en caso de error de script?

1

Tengo una secuencia de comandos launchd similar a cron ( StartCalendarInterval ) que hace una copia de seguridad de algunos datos del sitio web una vez al día:

<?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>com.example.backup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Volumes/Example/backup.sh</string>
    </array>
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>2</integer>
            <key>Minute</key>
            <integer>15</integer>
        </dict>
    </array>
    <key>StandardErrorPath</key>
    <string>/var/log/com.example/backup_error</string>
    <key>StandardOutPath</key>
    <string>/var/log/com.example/backup_output</string>
</dict>
</plist>

En casos raros, puede fallar cuando Internet no está disponible. La secuencia de comandos backup.sh luego establece un código de error adecuado que es mayor que 0.

Ahora me gustaría que el script se reinicie automáticamente una hora más tarde después de un error. Y una y otra vez hasta que no haya error. Pero no después de 24 horas para evitar que se ejecuten dos secuencias de comandos al mismo tiempo.

Creo que esto debe ser posible con ThrottleInterval y SuccessfulExit . Mi problema es que SuccessfulExit está vinculado a KeepAlive . No quiero que el script se ejecute todo el tiempo, pero solo una vez al día a través de StartCalendarInterval .

¿Es posible realizar mi tarea directamente con launchd? ¿O debería simplemente agregar wait 1 hour and try again after error a mi script? La secuencia de comandos requeriría recursos todo el tiempo cuando se configura de esta manera. Me gustaría evitar esto.

    
pregunta Haru 13.07.2015 - 01:55

1 respuesta

1

Parece que se puede hacer parcialmente. Básicamente, el problema fue que KeepAlive en combinación con SuccessfulExit implicaba un RunAtLoad (el programa se inició justo al inicio y no en el StartCalendarIntervall especificado). Configuración del parámetro adicional AfterInitialDemand (que no está documentado) cambiará este comportamiento y el programa se inicia primero a la hora del calendario especificada:

<?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>com.example.backup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Volumes/Example/backup.sh</string>
    </array>

    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>2</integer>
            <key>Minute</key>
            <integer>15</integer>
        </dict>
    </array>

    <key>KeepAlive</key>
    <dict>
        <key>SuccessfulExit</key>
        <false/>
        <key>AfterInitialDemand</key>
        <true/>
    </dict>
    <key>ThrottleInterval</key>
    <integer>3600</integer>

    <key>StandardErrorPath</key>
    <string>/var/log/com.example/backup_error</string>
    <key>StandardOutPath</key>
    <string>/var/log/com.example/backup_output</string>
</dict>
</plist>

El único problema es que si el programa / secuencia de comandos falla, ThrottleInterval anulará StartCalendarInterval , por lo que, dependiendo del tiempo de error y el intervalo establecido, el programa / secuencia de comandos no se iniciará exactamente a la hora del calendario especificada después de una el día ha transcurrido (suponiendo que haya fallado hasta ese momento) y puede continuar en las compensaciones de tiempo impar (hasta que tenga éxito).

Pero para resumir: el truco es el AfterInitialDemand no documentado establecido en true .

    
respondido por el Haru 15.07.2015 - 23:46

Lea otras preguntas en las etiquetas