Ping healthchecks.io when a check succeeds

Thank you very much @saspus and @kgorlen for your help!

In my case, I plan to continue to have my backup from the GUI:

Plus on the side a script that would check and ping if success.

So I’m playing with the CLI. But when I run duplicacy check it asks for my backblaze IDs. I’m surprised because the GUI doesn’t ask each time for these IDs. Where is the GUI taking them from?

You can still do that. Fix the version of duplicacy CLI (in duplicacy.json), so that web UI does not download a new one, and replace duplicacy_linux_… whatever the name is with your script, that will call actual duplicacy and do other work you need. Duplicacy WebUI is just a fancy scheduler, all the work is done by the CLI

Credentials are stored encrypted in duplicacy.json (or keychain, if supported), and passed to duplicacy CLI via environment variables.

Very helpful answer!! And so I guess that my script should forward all the commands to the duplicacy binary?

Yes, something like this:

#!/bin/bash

# remove the first argument which is this script
shift

#pass remaining argumentes to duplicacy 
"/config/bin/duplicacy_original_binary" "$@"

# Get return code
exit_code=$?

if [ $exit_code -eq 0 ]; then
    # success
    curl -L https://example.com/success
else
    # fail
    curl -L https://example.com/fail
fi

exit $exit_code

Environment variables will be inherited by the child process automatically.

Note, I haven’t tried it, so there could be bugs.

Thank very much @saspus ! Will try it tonight!

To fix the version of the CLI, what should I do? Should I set “cli_version” in duplicacy.json and put the path towards the script?

Set it to the current version, e.g. 3.2.4, so it won’t download a newer one in the future; let it download that version if it hasn’t done it yet, and then rename the existing duplicacy_linux_x64_3.2.4 in the bin folder to e.g duplicacy_linux_x64_3.2.4_orig; name your script duplicacy_linux_x64_3.2.4, and call duplicacy_linux_x64_3.2.4_orig from there.

Okay, I see! Thank you very much!

If in the script I add echo "Hello" at the beginning, should I see the “hello” in the logs from the web UI?

Okay, I found the issue: I had the restart duplicacy.

I’ve successfully finished to implement the script:

#!/bin/bash

script_dir="$(dirname "$(readlink -f "$0")")"

healthcheck_url=""
args=()

shift

while [ $# -gt 0 ]; do
  if [ "$1" = "--healthcheck" ] && [ $# -gt 1 ]; then
    healthcheck_url="$2"
    shift 2
  else
    args+=("$1")
    shift
  fi
done

"$script_dir/duplicacy_linux_x64_3.2.3" "${args[@]}"

exit_code=$?

if [ -n "$healthcheck_url" ]; then
  curl -s "$healthcheck_url/$exit_code" > /dev/null || true
fi

exit $exit_code

that I put in ~/.duplicacy-web/bin/duplicacy_linux_x64_0.0.0 and in the duplicacy.json I put "cli_version": "0.0.0".

Now when I run backup / check / prune etc, I can add an extra --healthcheck [URL] and after the Duplicacy command is executed, the URL [URL]/[EXIT_CODE] is pinged.

I tested the failure cases and it works perfectly!

Thank you so much @saspus for the guidance!!

1 Like

There looks to be a bug: if --healthchecks is passed without the URL it will pass through to duplicacy. I think you shall remove && [ $# -gt 1] or fail if --healthcheck exists but $2 does not look like an URL.

It is fine if it is passed to Duplicacy. Duplicacy would fail. And I also assume that I call the script correctly.

It seems that since yesterday (when I replaced the Duplicacy bin by my script), I don’t have stats anymore for storage size, revisions, activities. Any idea?

I would (in order)

  • check stats folder to confirm stats are actually missing
  • verify the command line passed to duplicacy check (in the log), maybe some flags got omitted.
  • try setting the version to actual valid duplicacy version instead of zero, in case webui alters functionality based on version (e.g. maybe early Duplicacy did not output stats and webui does not expect any from ancient version 0.0.0)
  • try launching Duplicacy with exec, in case webui communicates with the child process via some signals that bash does not forward (in that case you would need to trap them in your script) or some other form of IPC (but this seems unlikely). (Note this is just as a test, because nothing will get executed after exec — bash would be gone)

Thanks. I removed the incorrect comment.

I’m checking the folder stats. In stats/schedules/Daily - Backup & Check.stats, I see:

...
    {
        "name": "Daily - Backup \u0026 Check",
        "type": "backup",
        "id": "Data@Backblaze",
        "status": "success",
        "log": "backup-20250312-040001.log",
        "start": "2025-03-12T04:00:01.259275363+01:00",
        "end": "2025-03-12T04:01:58.951620991+01:00",
        "jobs": null
    },
    {
        "name": "Daily - Backup \u0026 Check",
        "type": "check",
        "id": "",
        "status": "success",
        "log": "check-20250312-040158.log",
        "start": "2025-03-12T04:01:58.951699109+01:00",
        "end": "2025-03-12T04:02:49.505925059+01:00",
        "jobs": null
    },
    {
        "name": "Daily - Backup \u0026 Check",
        "type": "backup",
        "id": "Data@Backblaze",
        "status": "success",
        "log": "backup-20250312-090515.log",
        "start": "2025-03-12T09:05:15.446650428+01:00",
        "end": "2025-03-12T09:08:09.117549344+01:00",
        "jobs": null
    },
    {
        "name": "Daily - Backup \u0026 Check",
        "type": "check",
        "id": "",
        "status": "success",
        "log": "check-20250312-090809.log",
        "start": "2025-03-12T09:08:09.117729259+01:00",
        "end": "2025-03-12T09:09:15.708582312+01:00",
        "jobs": null
    }
]

So it seems that stats for this schedule has been saved?

For stats/storages/Backblaze.stats, I see:

...
"2025-03-09": {
        "total-size": 328309145600,
        "total-chunks": 112137,
        "pruned-chunks": 0,
        "pruned-revisions": 0,
        "status": "Checked",
        "repositories": {
            "Data": {
                "revisions": 29,
                "total-size": 319604916224,
                "unique-size": 319604916224,
                "total-chunks": 108336
            }
        }
    },
    "2025-03-10": {
        "total-size": 328883765248,
        "total-chunks": 112341,
        "pruned-chunks": 0,
        "pruned-revisions": 0,
        "status": "Checked",
        "repositories": {
            "Data": {
                "revisions": 30,
                "total-size": 320185827328,
                "unique-size": 320185827328,
                "total-chunks": 108542
            }
        }
    },
    "2025-03-11": {
        "total-size": 0,
        "total-chunks": 0,
        "pruned-chunks": 0,
        "pruned-revisions": 9,
        "status": "Checked",
        "repositories": {}
    },
    "2025-03-12": {
        "total-size": 0,
        "total-chunks": 0,
        "pruned-chunks": 0,
        "pruned-revisions": 0,
        "status": "Checked",
        "repositories": {}
    }
}

I found one issue. I had added “&” in the name of my schedules. After removing “&” from the name, the stats of “Activities” & “New revisions” appeared again.

But there is still another issue. It still can’t see the latest stats for “storage size” + the “restore” page tells me there is no backup found.

If I make the Web UI use Duplicacy CLI (instead of my script), the “restore” page shows the backups.

If I make the Web UI use my script, the “restore” page doesn’t show the backups.

It is not a matter of name because when I put the version 0.0.0 in the name of Duplicy CLI, it still works. But as soon as I make the Web UI use my script, it doesn’t…

Any idea?

Try exec. Perhaps webgui communicates using pid of the spawned process.

If this resolves the issue — you would need to modify the scrip to spawn (with disown) another script to wait for current pid and then exec duplicacy to re-use pid; then there shall be no difference from the perspective of webui.

@saspus I’ve finally found the error! When I remove the first shift of my script before the while loop it all works! My understanding is that the first shift was removing the first argument?

So this is the script that works:

#!/bin/bash

script_dir="$(dirname "$(readlink -f "$0")")"

healthcheck_url=""
args=()

while [ $# -gt 0 ]; do
  if [ "$1" = "--healthcheck" ] && [ $# -gt 1 ]; then
    healthcheck_url="$2"
    shift 2
  else
    args+=("$1")
    shift
  fi
done

"$script_dir/duplicacy_linux_x64_3.2.3" "${args[@]}"

exit_code=$?

if [ -n "$healthcheck_url" ]; then
  curl -s "$healthcheck_url/$exit_code" > /dev/null || true
fi

exit $exit_code
1 Like

Interesting. Now that I think about it arguments don’t include the app name indeed as my example implied initially (unlike in C and similar languages)

But I thought you checked the arguments, because you mentioned you’ve checked the version and it was after checking arguments in the list :).

Glad it works now

No worries, you disclaimed you didn’t test! I learnt things too. And you helped me more than enough! Would have never been able to do this at all without your help :slight_smile:

Hopefully now you don’t see me again :joy: