Prolog and Epilog Scripts

An action can optionally execute a script before the action runs or after it finishes.

action_scripts

In the action document, click a Choose… button to pick a script to execute. Click the X button to remove it.

What is a Script? More Info

Scripts can be used to prepare an archive or volume. For example, a prolog script can connect to a NAS device that doesn't auto-mount. They can also perform tasks based on the success or failure of an action, like sending a text message to the IT department if a verify action fails.

Prolog Script

The prolog script is run before the command begins.

A prolog script can cancel the command by exiting with an error. For POSIX scripts and executables, a non-zero exit status will cancel the action. For AppleScripts, throw a non-zero error in the top-level handler.

Exiting With an Error in AppleScript Details

Anything output by the script to stdout is logged as action details. Anything output to stderr is logged as a warning.

Epilog Script

The epilog script runs after the command finishes (either successfully or unsuccessfully).

The exit status of the epilog script does not affect the command, but a non-zero status and any output are logged.

Has UI

If your script interacts with the user (shows a window, speaks text, launches a macOS application, …), it will require an execution environment that allows it access to the user's GUI session.

Checking the Has UI option next to the script name prompts QRecall to launch the script in the user's GUI session context—if possible.

If not checked, or the user isn't logged in, the script will be executed in a background session context. In that context, attempts to interact through the graphical user interface will fail.

Script Environment

A script inherits a set of environment values that tells it a lot about the action. Most programming and scripting languages have access to the process' environment values. For example, sh makes all environment values available as shell variables, like this:

TITLE="${QR_COMMAND_TITLE}"

In AppleScript, environment values are available through the system attribute object, like this:

set actionTitle to (system attribute "QR_COMMAND_TITLE")

These are the common values passed to all action scripts:

QR_PROCESS_IDPID of the command process.
QR_COMMAND_IDA unique (while running) process identifier.
QR_ACTION_IDThe unique identifier of the action (only present for commands started by an action).
QR_COMMAND_TYPEThe type of command ("capture", "merge", "compact", ...).
QR_COMMAND_TYPE_DISPLAYLocalized QR_COMMAND_TYPE.
QR_COMMAND_FUNCTIONAL_TITLEQRecall's description of the action.
QR_COMMAND_TITLEThe title of the action as it appears in the monitor & log.
Will be QR_COMMAND_FUNCTIONAL_TITLE if a custom title wasn't assigned.

For commands that perform their task on an archive, these values will be present:

QR_ARCHIVE_PATHAbsolute path to the archive.
QR_ARCHIVE_NAMEName of the archive document.
QR_ARCHIVE_NAME_DISPLAYArchive display name (as it appears in the Finder).
QR_ARCHIVE_REACHABLE1 if archive is currently reachable, 0 otherwise.
QR_ARCHIVE_UUIDArchive's unique identifier (if reachable)
QR_ARCHIVE_VOLUME_NAMEName of volume containing the archive
QR_ARCHIVE_VOLUME_NAME_DISPLAYVolume's display name (as it appears in the Finder)
QR_ARCHIVE_VOLUME_UUIDVolume's UUID (if it has one and archive is reachable)
QR_ARCHIVE_VOLUME_MOUNTPOINTVolume mount point path (if archive is reachable)

If the command uses a stack, these additional values will be present (if the archive is reachable):

QR_STACK_UUIDStack's unique identifier (always, even if unreachable).
QR_STACK_TYPEThe type of stack (Document, AWS S3, …).
QR_STACK_URLThe container's URL (if it has one)
QR_STACK_CONTAINERThe stack container's shorthand name.
QR_STACK_DESCRIPTIONA readable description of the container.
QR_STACK_DISPLAY_NAMEThe name of stack as it appears in QRecall.

In addition to all of the values present when the prolog script is run, these additional values are available to epilog scripts:

QR_COMMAND_SUCCESS1 if command finished normally, 0 otherwise
QR_COMMAND_EXCEPTIONIf unsuccessful, the reason why
QR_COMMAND_CANCELEDIf the command was stopped, the source:
  1. user (pressed the stop button)
  2. lost access to archive
  3. schedule condition
  4. process received TERM signal
  5. prolog script
  6. command stopped itself

Example

Processes like database servers are notoriously difficult to capture because they maintain many open files which don't always represent their current state. So simply capturing the database files on the volume will not capture all of it data, and might even result in an invalid copy as the files on disk are often out of sync with what's in memory.

For this example, we want to capture a current, complete, and valid copy of a set of MySQL databases.

The first solution uses a prolog bash script to export all of the MySQL database tables to an SQL file before the capture begins. The capture action will then capture the static snapshot of the database, which can later be used to restore the databases using a MySQL import command.

#!/bin/bash
# dump all the databases to an SQL text file so we
#   capture a clean snapshot of the tables
SNAPSHOT=~/Admin/MySQLBackup.daily.sql
mysqldump --opt --all-databases --user=dbadmin > "${SNAPSHOT}"
echo "MySQL snapshot written to ${SNAPSHOT}"

An alternative solution would be to shutdown the database server for the duration of the nightly capture action, and then start it again once the capture is finished.

Note that this script runs as both the prolog and epilog script of the capture action. It examines the QR_COMMAND_SUCCESS value (which is only present for epilog scripts) to determine what to do.

#!/bin/bash
if [[ -z "${QR_COMMAND_SUCCESS}" ]]
then
	# The QR_COMMAND_SUCCESS variable is NOT set,
	#  which means this is the prolog:
	# Shutdown the database so that all data is
	#  written to disk and does not change
	#  while the backup is in progress.
	mysql.server stop
	echo "MySQL server shutdown"
else
	# The QR_COMMAND_SUCCESS variable is set,
	#  which means this is the epilog:
	# Fire up the database again.
	mysql.server start
	echo "MySQL server restarted"
fi