Pēteris Caune
4 years ago
No known key found for this signature in database
GPG Key ID: E28D7679E9A9EDE2
35 changed files with 817 additions and 20 deletions
-
1CHANGELOG.md
-
29hc/front/management/commands/render_docs.py
-
1hc/front/urls.py
-
26hc/front/views.py
-
2static/css/channels.css
-
21static/css/docs.css
-
2templates/base.html
-
34templates/docs/bash.html
-
39templates/docs/bash.md
-
7templates/docs/csharp.html
-
10templates/docs/csharp.md
-
12templates/docs/email.html
-
16templates/docs/email.md
-
26templates/docs/introduction.html
-
26templates/docs/introduction.md
-
13templates/docs/javascript.html
-
17templates/docs/javascript.md
-
30templates/docs/measuring_script_run_time.html
-
35templates/docs/measuring_script_run_time.md
-
109templates/docs/monitoring_cron_jobs.html
-
113templates/docs/monitoring_cron_jobs.md
-
4templates/docs/php.html
-
7templates/docs/php.md
-
23templates/docs/powershell.html
-
29templates/docs/powershell.md
-
32templates/docs/python.html
-
37templates/docs/python.md
-
7templates/docs/ruby.html
-
10templates/docs/ruby.md
-
24templates/docs/signalling_failures.html
-
28templates/docs/signalling_failures.md
-
38templates/front/base_docs.html
-
4templates/front/docs_cron.html
-
3templates/front/docs_nav_item.html
-
22templates/front/docs_single.html
@ -0,0 +1,29 @@ |
|||
import os |
|||
|
|||
from django.conf import settings |
|||
from django.core.management.base import BaseCommand |
|||
import markdown |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = "Renders Markdown to HTML" |
|||
|
|||
def handle(self, *args, **options): |
|||
extensions = ["fenced_code", "codehilite", "tables"] |
|||
ec = {"codehilite": {"css_class": "highlight"}} |
|||
|
|||
docs_path = os.path.join(settings.BASE_DIR, "templates/docs") |
|||
for doc in os.listdir(docs_path): |
|||
if not doc.endswith(".md"): |
|||
continue |
|||
|
|||
print("Rendering %s" % doc) |
|||
|
|||
src_path = os.path.join(docs_path, doc) |
|||
dst_path = os.path.join(docs_path, doc[:-3] + ".html") |
|||
|
|||
text = open(src_path, "r", encoding="utf-8").read() |
|||
html = markdown.markdown(text, extensions=extensions, extension_configs=ec) |
|||
|
|||
with open(dst_path, "w", encoding="utf-8") as f: |
|||
f.write(html) |
@ -0,0 +1,34 @@ |
|||
<h1>Shell scripts</h1> |
|||
<p>You can easily add SITE_NAME monitoring to a shell script. All you |
|||
have to do is make a HTTP request at the end of the script. curl and wget |
|||
are two common command line HTTP clients for that.</p> |
|||
<h2>Using curl</h2> |
|||
<div class="highlight"><pre><span></span><span class="ch">#!/bin/sh</span> |
|||
|
|||
<span class="c1"># Exit immediately if any command exits with a non-zero status:</span> |
|||
<span class="nb">set</span> -e |
|||
|
|||
<span class="c1"># Do the work here</span> |
|||
<span class="nb">echo</span> <span class="s2">"Pretending to to make backups..."</span> |
|||
sleep <span class="m">5</span> |
|||
<span class="nb">echo</span> <span class="s2">"Backup complete!"</span> |
|||
|
|||
<span class="c1"># As the last thing, ping SITE_NAME using curl:</span> |
|||
<span class="hll">curl --retry <span class="m">3</span> PING_URL |
|||
</span></pre></div> |
|||
|
|||
|
|||
<h2>Using wget</h2> |
|||
<div class="highlight"><pre><span></span><span class="ch">#!/bin/sh</span> |
|||
|
|||
<span class="c1"># Exit immediately if any command exits with a non-zero status:</span> |
|||
<span class="nb">set</span> -e |
|||
|
|||
<span class="c1"># Do the work here</span> |
|||
<span class="nb">echo</span> <span class="s2">"Pretending to to generate reports..."</span> |
|||
sleep <span class="m">5</span> |
|||
<span class="nb">echo</span> <span class="s2">"Report generation complete!"</span> |
|||
|
|||
<span class="c1"># As the last thing, ping SITE_NAME using wget:</span> |
|||
<span class="hll">wget PING_URL -O /dev/null |
|||
</span></pre></div> |
@ -0,0 +1,39 @@ |
|||
# Shell scripts |
|||
|
|||
You can easily add SITE_NAME monitoring to a shell script. All you |
|||
have to do is make a HTTP request at the end of the script. curl and wget |
|||
are two common command line HTTP clients for that. |
|||
|
|||
## Using curl |
|||
|
|||
```bash hl_lines="12" |
|||
#!/bin/sh |
|||
|
|||
# Exit immediately if any command exits with a non-zero status: |
|||
set -e |
|||
|
|||
# Do the work here |
|||
echo "Pretending to to make backups..." |
|||
sleep 5 |
|||
echo "Backup complete!" |
|||
|
|||
# As the last thing, ping SITE_NAME using curl: |
|||
curl --retry 3 PING_URL |
|||
``` |
|||
|
|||
## Using wget |
|||
|
|||
```bash hl_lines="12" |
|||
#!/bin/sh |
|||
|
|||
# Exit immediately if any command exits with a non-zero status: |
|||
set -e |
|||
|
|||
# Do the work here |
|||
echo "Pretending to to generate reports..." |
|||
sleep 5 |
|||
echo "Report generation complete!" |
|||
|
|||
# As the last thing, ping SITE_NAME using wget: |
|||
wget PING_URL -O /dev/null |
|||
``` |
@ -0,0 +1,7 @@ |
|||
<h1>C</h1> |
|||
<p>Below is an example of making a HTTP request to SITE_NAME from C#.</p> |
|||
<div class="highlight"><pre><span></span><span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">client</span> <span class="p">=</span> <span class="k">new</span> <span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">WebClient</span><span class="p">())</span> |
|||
<span class="p">{</span> |
|||
<span class="n">client</span><span class="p">.</span><span class="n">DownloadString</span><span class="p">(</span><span class="s">"PING_URL"</span><span class="p">);</span> |
|||
<span class="p">}</span> |
|||
</pre></div> |
@ -0,0 +1,10 @@ |
|||
# C# |
|||
|
|||
Below is an example of making a HTTP request to SITE_NAME from C#. |
|||
|
|||
```csharp |
|||
using (var client = new System.Net.WebClient()) |
|||
{ |
|||
client.DownloadString("PING_URL"); |
|||
} |
|||
``` |
@ -0,0 +1,12 @@ |
|||
<h1>Email</h1> |
|||
<p>As an alternative to HTTP/HTTPS requests, you can "ping" checks by |
|||
sending an emails to special email addresses.</p> |
|||
<h2>Use Case: Email Delivery Monitoring</h2> |
|||
<p>Consider a cron job which runs weekly and sends weekly email |
|||
reports to a list of e-mail addresses. You have already set up a check to get alerted |
|||
when your cron job fails to run. But what you ultimately want to check is if |
|||
<strong>your emails are getting sent and delivered</strong>.</p> |
|||
<p>The solution: set up another check, and add its email address to your list of |
|||
recipient email addresses. Set its Period to 1 week. As long as your weekly email |
|||
script runs correctly, and there are no email delivery issues, |
|||
SITE_NAME will regularly receive an email, and the check and will stay up.</p> |
@ -0,0 +1,16 @@ |
|||
# Email |
|||
|
|||
As an alternative to HTTP/HTTPS requests, you can "ping" checks by |
|||
sending an emails to special email addresses. |
|||
|
|||
## Use Case: Email Delivery Monitoring |
|||
|
|||
Consider a cron job which runs weekly and sends weekly email |
|||
reports to a list of e-mail addresses. You have already set up a check to get alerted |
|||
when your cron job fails to run. But what you ultimately want to check is if |
|||
**your emails are getting sent and delivered**. |
|||
|
|||
The solution: set up another check, and add its email address to your list of |
|||
recipient email addresses. Set its Period to 1 week. As long as your weekly email |
|||
script runs correctly, and there are no email delivery issues, |
|||
SITE_NAME will regularly receive an email, and the check and will stay up. |
@ -0,0 +1,26 @@ |
|||
<h2>SITE_NAME</h2> |
|||
<p>SITE_NAME is a service for monitoring cron jobs and similar periodic processes:</p> |
|||
<ul> |
|||
<li>SITE_NAME <strong>listens for pings</strong> from services being monitored.</li> |
|||
<li>It <strong>keeps silent</strong> as long as pings arrive on time.</li> |
|||
<li>It <strong>raises an alert</strong> as soon as a ping does not arrive on time.</li> |
|||
</ul> |
|||
<p>SITE_NAME works as a <a href="https://en.wikipedia.org/wiki/Dead_man%27s_switch">dead man's switch</a> for processes that need to |
|||
run continuously or on regular, known schedule:</p> |
|||
<ul> |
|||
<li>filesystem, database backups</li> |
|||
<li>task queues</li> |
|||
<li>database replication status</li> |
|||
<li>report generation scripts</li> |
|||
<li>periodic data import and sync jobs</li> |
|||
<li>periodic antivirus scans</li> |
|||
<li>DDNS updater scripts</li> |
|||
<li>SSL renewal scripts</li> |
|||
</ul> |
|||
<p>SITE_NAME is <em>not</em> the right tool for:</p> |
|||
<ul> |
|||
<li>monitoring website uptime by probing it with HTTP requests</li> |
|||
<li>collecting application performance metrics</li> |
|||
<li>error tracking</li> |
|||
<li>log aggregation</li> |
|||
</ul> |
@ -0,0 +1,26 @@ |
|||
## SITE_NAME |
|||
|
|||
SITE_NAME is a service for monitoring cron jobs and similar periodic processes: |
|||
|
|||
* SITE_NAME **listens for pings** from services being monitored. |
|||
* It **keeps silent** as long as pings arrive on time. |
|||
* It **raises an alert** as soon as a ping does not arrive on time. |
|||
|
|||
SITE_NAME works as a [dead man's switch](https://en.wikipedia.org/wiki/Dead_man%27s_switch) for processes that need to |
|||
run continuously or on regular, known schedule: |
|||
|
|||
* filesystem, database backups |
|||
* task queues |
|||
* database replication status |
|||
* report generation scripts |
|||
* periodic data import and sync jobs |
|||
* periodic antivirus scans |
|||
* DDNS updater scripts |
|||
* SSL renewal scripts |
|||
|
|||
SITE_NAME is *not* the right tool for: |
|||
|
|||
* monitoring website uptime by probing it with HTTP requests |
|||
* collecting application performance metrics |
|||
* error tracking |
|||
* log aggregation |
@ -0,0 +1,13 @@ |
|||
<h1>Javascript</h1> |
|||
<p>Below is an example of making a HTTP request to SITE_NAME from Node.js.</p> |
|||
<div class="highlight"><pre><span></span><span class="kd">var</span> <span class="nx">https</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'https'</span><span class="p">);</span> |
|||
<span class="nx">https</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">"PING_URL"</span><span class="p">);</span> |
|||
</pre></div> |
|||
|
|||
|
|||
<p>You can also send pings from a browser environment. SITE_NAME sets the |
|||
<code>Access-Control-Allow-Origin:*</code> CORS header, so cross-domain AJAX requests work.</p> |
|||
<div class="highlight"><pre><span></span><span class="kd">var</span> <span class="nx">xhr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">();</span> |
|||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="s1">'GET'</span><span class="p">,</span> <span class="s1">'PING_URL'</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span> |
|||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span> |
|||
</pre></div> |
@ -0,0 +1,17 @@ |
|||
# Javascript |
|||
|
|||
Below is an example of making a HTTP request to SITE_NAME from Node.js. |
|||
|
|||
```js |
|||
var https = require('https'); |
|||
https.get("PING_URL"); |
|||
``` |
|||
|
|||
You can also send pings from a browser environment. SITE_NAME sets the |
|||
`Access-Control-Allow-Origin:*` CORS header, so cross-domain AJAX requests work. |
|||
|
|||
```js |
|||
var xhr = new XMLHttpRequest(); |
|||
xhr.open('GET', 'PING_URL', true); |
|||
xhr.send(null); |
|||
``` |
@ -0,0 +1,30 @@ |
|||
<h1>Measuring Script Run Time</h1> |
|||
<p>Append <code>/start</code> to a ping URL and use it to signal when a job starts. |
|||
After receiving a start signal, Healthchecks.io will show the check as "Started". |
|||
It will store the "start" events and display the job execution times. The job |
|||
execution times are calculated as the time gaps between adjacent "start" and |
|||
"complete" events.</p> |
|||
<p>Signalling a start kicks off a separate timer: the job now <strong>must</strong> signal a |
|||
success within its configured "Grace Time", or it will get marked as "down".</p> |
|||
<p>Below is a code example in Python:</p> |
|||
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">requests</span> |
|||
<span class="n">URL</span> <span class="o">=</span> <span class="s2">"PING_URL"</span> |
|||
|
|||
|
|||
<span class="c1"># "/start" kicks off a timer: if the job takes longer than</span> |
|||
<span class="c1"># the configured grace time, the check will be marked as "down"</span> |
|||
<span class="k">try</span><span class="p">:</span> |
|||
<span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">URL</span> <span class="o">+</span> <span class="s2">"/start"</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span> |
|||
<span class="k">except</span> <span class="n">requests</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">RequestException</span><span class="p">:</span> |
|||
<span class="c1"># If the network request fails for any reason, we don't want</span> |
|||
<span class="c1"># it to prevent the main job from running</span> |
|||
<span class="k">pass</span> |
|||
|
|||
|
|||
<span class="c1"># TODO: run the job here</span> |
|||
<span class="n">fib</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> |
|||
<span class="k">print</span><span class="p">(</span><span class="s2">"F(42) = </span><span class="si">%d</span><span class="s2">"</span> <span class="o">%</span> <span class="n">fib</span><span class="p">(</span><span class="mi">42</span><span class="p">))</span> |
|||
|
|||
<span class="c1"># Signal success:</span> |
|||
<span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">URL</span><span class="p">)</span> |
|||
</pre></div> |
@ -0,0 +1,35 @@ |
|||
# Measuring Script Run Time |
|||
|
|||
Append `/start` to a ping URL and use it to signal when a job starts. |
|||
After receiving a start signal, Healthchecks.io will show the check as "Started". |
|||
It will store the "start" events and display the job execution times. The job |
|||
execution times are calculated as the time gaps between adjacent "start" and |
|||
"complete" events. |
|||
|
|||
Signalling a start kicks off a separate timer: the job now **must** signal a |
|||
success within its configured "Grace Time", or it will get marked as "down". |
|||
|
|||
Below is a code example in Python: |
|||
|
|||
```python |
|||
import requests |
|||
URL = "PING_URL" |
|||
|
|||
|
|||
# "/start" kicks off a timer: if the job takes longer than |
|||
# the configured grace time, the check will be marked as "down" |
|||
try: |
|||
requests.get(URL + "/start", timeout=5) |
|||
except requests.exceptions.RequestException: |
|||
# If the network request fails for any reason, we don't want |
|||
# it to prevent the main job from running |
|||
pass |
|||
|
|||
|
|||
# TODO: run the job here |
|||
fib = lambda n: n if n < 2 else fib(n - 1) + fib(n - 2) |
|||
print("F(42) = %d" % fib(42)) |
|||
|
|||
# Signal success: |
|||
requests.get(URL) |
|||
``` |
@ -0,0 +1,109 @@ |
|||
<h2>Monitoring Cron Jobs</h2> |
|||
<p>SITE_NAME is perfectly suited for monitoring cron jobs. |
|||
Let's look at an example: a machine with the following cron job:</p> |
|||
<div class="highlight"><pre><span></span>$ crontab -l |
|||
<span class="c1"># m h dom mon dow command</span> |
|||
<span class="m">8</span> <span class="m">6</span> * * * /home/user/backup.sh |
|||
</pre></div> |
|||
|
|||
|
|||
<p>You can use SITE_NAME to get a notification whenever the <code>backup.sh</code> script does not |
|||
complete successfully. Here is how to set that up.</p> |
|||
<ol> |
|||
<li> |
|||
<p>If you have not already, sign up for a free SITE_NAME account.</p> |
|||
</li> |
|||
<li> |
|||
<p>In your SITE_NAME account, <strong>add a new check</strong>.</p> |
|||
<p>Note: in SITE_NAME, a <strong>check</strong> represents a single service you want to |
|||
monitor. For example, a single cron job. For each additional cron job you will |
|||
create another check. SITE_NAME pricing plans are structured primarily |
|||
around how many checks you can have in the account.</p> |
|||
</li> |
|||
<li> |
|||
<p>Give the check <strong>a meaningful name</strong>. Good naming will become |
|||
increasingly important as you add more checks to your account.</p> |
|||
</li> |
|||
<li> |
|||
<p>Edit the check's <strong>schedule</strong>:</p> |
|||
<ul> |
|||
<li>change its type from "Simple" to "Cron"</li> |
|||
<li>enter <code>8 6 * * *</code> in the cron epression field</li> |
|||
<li>set the timezone to match your machine's timezone</li> |
|||
</ul> |
|||
</li> |
|||
<li> |
|||
<p>Take note of your check's unique <strong>ping URL</strong></p> |
|||
</li> |
|||
</ol> |
|||
<p>Finally, edit your crontab and append a curl or wget call after the command:</p> |
|||
<div class="highlight"><pre><span></span>$ crontab -e |
|||
<span class="c1"># m h dom mon dow command</span> |
|||
<span class="m">8</span> <span class="m">6</span> * * * /home/user/backup.sh <span class="o">&&</span> curl -fsS --retry <span class="m">3</span> PING_URL > /dev/null |
|||
</pre></div> |
|||
|
|||
|
|||
<p>Now, each time your cron job runs, it will send a HTTP request to the ping URL.</p> |
|||
<p>Since SITE_NAME knows the schedule of your cron job, it can calculate |
|||
the dates and times when the job should run. As soon as your cron job doesn't |
|||
report at an expected time, SITE_NAME will send you a notification.</p> |
|||
<p>This monitoring technique takes care of various failure scenarios that could |
|||
potentially go unnoticed otherwise:</p> |
|||
<ul> |
|||
<li>The whole machine goes down (power outage, janitor stumbles on wires, VPS provider problems, etc.)</li> |
|||
<li>cron daemon is not running, or has invalid configuration</li> |
|||
<li>cron does start your task, but the task exits with non-zero exit code</li> |
|||
</ul> |
|||
<h2>Curl Options</h2> |
|||
<p>The extra options tells curl to not print anything to standard output unless |
|||
there is an error. Feel free to adjust the curl options to suit your needs.</p> |
|||
<table class="table curl-opts"> |
|||
<tr> |
|||
<th>&&</th> |
|||
<td>Run curl only if <code>/home/user/backup.sh</code> exits with an exit code 0</td> |
|||
</tr> |
|||
<tr> |
|||
<th> |
|||
-f, --fail |
|||
</th> |
|||
<td>Makes curl treat non-200 responses as errors</td> |
|||
</tr> |
|||
<tr> |
|||
<th>-s, --silent</th> |
|||
<td>Silent or quiet mode. Don't show progress meter or error messages.</td> |
|||
</tr> |
|||
<tr> |
|||
<th>-S, --show-error</th> |
|||
<td>When used with -s it makes curl show error message if it fails.</td> |
|||
</tr> |
|||
<tr> |
|||
<th>--retry <num></th> |
|||
<td> |
|||
If a transient error is returned when curl tries to perform a |
|||
transfer, it will retry this number of times before giving up. |
|||
Setting the number to 0 makes curl do no retries |
|||
(which is the default). Transient error means either: a timeout, |
|||
an FTP 4xx response code or an HTTP 5xx response code. |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th>> /dev/null</th> |
|||
<td> |
|||
Redirect curl's stdout to /dev/null (error messages go to stderr,) |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
|
|||
<h2>Looking up Your Machine's Time Zone</h2> |
|||
<p>On modern GNU/Linux systems, you can look up the time zone using the |
|||
<code>timedatectl status</code> command and looking for "Time zone" in its output:</p> |
|||
<div class="highlight"><pre><span></span>$ timedatectl status |
|||
|
|||
Local time: C 2020-01-23 12:35:50 EET |
|||
Universal time: C 2020-01-23 10:35:50 UTC |
|||
RTC time: C 2020-01-23 10:35:50 |
|||
<span class="hll"> Time zone: Europe/Riga (EET, +0200) |
|||
</span>System clock synchronized: yes |
|||
NTP service: active |
|||
RTC in local TZ: no |
|||
</pre></div> |
@ -0,0 +1,113 @@ |
|||
## Monitoring Cron Jobs |
|||
|
|||
SITE_NAME is perfectly suited for monitoring cron jobs. |
|||
Let's look at an example: a machine with the following cron job: |
|||
|
|||
```bash |
|||
$ crontab -l |
|||
# m h dom mon dow command |
|||
8 6 * * * /home/user/backup.sh |
|||
``` |
|||
|
|||
You can use SITE_NAME to get a notification whenever the `backup.sh` script does not |
|||
complete successfully. Here is how to set that up. |
|||
|
|||
1. If you have not already, sign up for a free SITE_NAME account. |
|||
|
|||
1. In your SITE_NAME account, **add a new check**. |
|||
|
|||
Note: in SITE_NAME, a **check** represents a single service you want to |
|||
monitor. For example, a single cron job. For each additional cron job you will |
|||
create another check. SITE_NAME pricing plans are structured primarily |
|||
around how many checks you can have in the account. |
|||
|
|||
1. Give the check **a meaningful name**. Good naming will become |
|||
increasingly important as you add more checks to your account. |
|||
|
|||
1. Edit the check's **schedule**: |
|||
|
|||
* change its type from "Simple" to "Cron" |
|||
* enter `8 6 * * *` in the cron epression field |
|||
* set the timezone to match your machine's timezone |
|||
|
|||
1. Take note of your check's unique **ping URL** |
|||
|
|||
Finally, edit your crontab and append a curl or wget call after the command: |
|||
|
|||
```bash |
|||
$ crontab -e |
|||
# m h dom mon dow command |
|||
8 6 * * * /home/user/backup.sh && curl -fsS --retry 3 PING_URL > /dev/null |
|||
``` |
|||
|
|||
Now, each time your cron job runs, it will send a HTTP request to the ping URL. |
|||
|
|||
Since SITE_NAME knows the schedule of your cron job, it can calculate |
|||
the dates and times when the job should run. As soon as your cron job doesn't |
|||
report at an expected time, SITE_NAME will send you a notification. |
|||
|
|||
This monitoring technique takes care of various failure scenarios that could |
|||
potentially go unnoticed otherwise: |
|||
|
|||
* The whole machine goes down (power outage, janitor stumbles on wires, VPS provider problems, etc.) |
|||
* cron daemon is not running, or has invalid configuration |
|||
* cron does start your task, but the task exits with non-zero exit code |
|||
|
|||
## Curl Options |
|||
|
|||
The extra options tells curl to not print anything to standard output unless |
|||
there is an error. Feel free to adjust the curl options to suit your needs. |
|||
|
|||
<table class="table curl-opts"> |
|||
<tr> |
|||
<th>&&</th> |
|||
<td>Run curl only if <code>/home/user/backup.sh</code> exits with an exit code 0</td> |
|||
</tr> |
|||
<tr> |
|||
<th> |
|||
-f, --fail |
|||
</th> |
|||
<td>Makes curl treat non-200 responses as errors</td> |
|||
</tr> |
|||
<tr> |
|||
<th>-s, --silent</th> |
|||
<td>Silent or quiet mode. Don't show progress meter or error messages.</td> |
|||
</tr> |
|||
<tr> |
|||
<th>-S, --show-error</th> |
|||
<td>When used with -s it makes curl show error message if it fails.</td> |
|||
</tr> |
|||
<tr> |
|||
<th>--retry <num></th> |
|||
<td> |
|||
If a transient error is returned when curl tries to perform a |
|||
transfer, it will retry this number of times before giving up. |
|||
Setting the number to 0 makes curl do no retries |
|||
(which is the default). Transient error means either: a timeout, |
|||
an FTP 4xx response code or an HTTP 5xx response code. |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th>> /dev/null</th> |
|||
<td> |
|||
Redirect curl's stdout to /dev/null (error messages go to stderr,) |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
|
|||
## Looking up Your Machine's Time Zone |
|||
|
|||
On modern GNU/Linux systems, you can look up the time zone using the |
|||
`timedatectl status` command and looking for "Time zone" in its output: |
|||
|
|||
```text hl_lines="6" |
|||
$ timedatectl status |
|||
|
|||
Local time: C 2020-01-23 12:35:50 EET |
|||
Universal time: C 2020-01-23 10:35:50 UTC |
|||
RTC time: C 2020-01-23 10:35:50 |
|||
Time zone: Europe/Riga (EET, +0200) |
|||
System clock synchronized: yes |
|||
NTP service: active |
|||
RTC in local TZ: no |
|||
``` |
@ -0,0 +1,4 @@ |
|||
<h1>PHP</h1> |
|||
<p>Below is an example of making a HTTP request to SITE_NAME from PHP.</p> |
|||
<div class="highlight"><pre><span></span><span class="x">file_get_contents('https://hc-ping.com/your-uuid-here');</span> |
|||
</pre></div> |
@ -0,0 +1,7 @@ |
|||
# PHP |
|||
|
|||
Below is an example of making a HTTP request to SITE_NAME from PHP. |
|||
|
|||
```php |
|||
file_get_contents('https://hc-ping.com/your-uuid-here'); |
|||
``` |
@ -0,0 +1,23 @@ |
|||
<h1>PowerShell</h1> |
|||
<p>You can use <a href="https://msdn.microsoft.com/en-us/powershell/mt173057.aspx">PowerShell</a> |
|||
and Windows Task Scheduler to automate various tasks on a Windows system. |
|||
From within a PowerShell script it is also easy to ping SITE_NAME.</p> |
|||
<p>Here is a simple PowerShell script that pings SITE_NAME. When scheduled to |
|||
run with Task Scheduler, it will essentially just send regular "I'm alive" messages. |
|||
You can of course extend it to do more things.</p> |
|||
<div class="highlight"><pre><span></span><span class="c1"># inside a PowerShell script:</span> |
|||
Invoke-RestMethod PING_URL |
|||
</pre></div> |
|||
|
|||
|
|||
<p>Save the above to e.g. <code>C:\Scripts\healthchecks.ps1</code>. |
|||
Then use the following command in a Scheduled Task to run the script:</p> |
|||
<div class="highlight"><pre><span></span>powershell.exe -ExecutionPolicy bypass -File C:<span class="se">\S</span>cripts<span class="se">\h</span>ealthchecks.ps1 |
|||
</pre></div> |
|||
|
|||
|
|||
<p>In simple cases, you can also pass the script to PowerShell directly, |
|||
using the "-command" argument:</p> |
|||
<div class="highlight"><pre><span></span><span class="c1"># Without an underlying script, passing the command to PowerShell directly:</span> |
|||
powershell.exe -command <span class="p">&</span><span class="o">{</span>Invoke-RestMethod PING_URL<span class="o">}</span> |
|||
</pre></div> |
@ -0,0 +1,29 @@ |
|||
# PowerShell |
|||
|
|||
You can use [PowerShell](https://msdn.microsoft.com/en-us/powershell/mt173057.aspx) |
|||
and Windows Task Scheduler to automate various tasks on a Windows system. |
|||
From within a PowerShell script it is also easy to ping SITE_NAME. |
|||
|
|||
Here is a simple PowerShell script that pings SITE_NAME. When scheduled to |
|||
run with Task Scheduler, it will essentially just send regular "I'm alive" messages. |
|||
You can of course extend it to do more things. |
|||
|
|||
```bash |
|||
# inside a PowerShell script: |
|||
Invoke-RestMethod PING_URL |
|||
``` |
|||
|
|||
Save the above to e.g. `C:\Scripts\healthchecks.ps1`. |
|||
Then use the following command in a Scheduled Task to run the script: |
|||
|
|||
```bash |
|||
powershell.exe -ExecutionPolicy bypass -File C:\Scripts\healthchecks.ps1 |
|||
``` |
|||
|
|||
In simple cases, you can also pass the script to PowerShell directly, |
|||
using the "-command" argument: |
|||
|
|||
```bash |
|||
# Without an underlying script, passing the command to PowerShell directly: |
|||
powershell.exe -command &{Invoke-RestMethod PING_URL} |
|||
``` |
@ -0,0 +1,32 @@ |
|||
<h1>Python</h1> |
|||
<p>If you are already using the requests library, it's convenient to also use it here:</p> |
|||
<div class="highlight"><pre><span></span><span class="c1"># using requests:</span> |
|||
<span class="kn">import</span> <span class="nn">requests</span> |
|||
<span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"PING_URL"</span><span class="p">)</span> |
|||
</pre></div> |
|||
|
|||
|
|||
<p>Otherwise, you can use the urllib standard module.</p> |
|||
<div class="highlight"><pre><span></span><span class="c1"># urllib with python 3.x:</span> |
|||
<span class="kn">import</span> <span class="nn">urllib.request</span> |
|||
<span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s2">"PING_URL"</span><span class="p">)</span> |
|||
</pre></div> |
|||
|
|||
|
|||
<div class="highlight"><pre><span></span><span class="c1"># urllib with python 2.x:</span> |
|||
<span class="kn">import</span> <span class="nn">urllib</span> |
|||
<span class="n">urllib</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s2">"PING_URL"</span><span class="p">)</span> |
|||
</pre></div> |
|||
|
|||
|
|||
<p>You can include additional diagnostic information in the in the request body (for POST requests), or in the "User-Agent" request header:</p> |
|||
<div class="highlight"><pre><span></span><span class="c1"># Passing diagnostic information in the POST body:</span> |
|||
<span class="kn">import</span> <span class="nn">requests</span> |
|||
<span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"PING_URL"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="s2">"temperature=-7"</span><span class="p">)</span> |
|||
</pre></div> |
|||
|
|||
|
|||
<div class="highlight"><pre><span></span><span class="c1"># Passing diagnostic information in the User-Agent header:</span> |
|||
<span class="kn">import</span> <span class="nn">requests</span> |
|||
<span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"PING_URL"</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">"User-Agent"</span><span class="p">:</span> <span class="s2">"temperature=-7"</span><span class="p">})</span> |
|||
</pre></div> |
@ -0,0 +1,37 @@ |
|||
# Python |
|||
|
|||
If you are already using the requests library, it's convenient to also use it here: |
|||
|
|||
```python |
|||
# using requests: |
|||
import requests |
|||
requests.get("PING_URL") |
|||
``` |
|||
|
|||
Otherwise, you can use the urllib standard module. |
|||
|
|||
```python |
|||
# urllib with python 3.x: |
|||
import urllib.request |
|||
urllib.request.urlopen("PING_URL") |
|||
``` |
|||
|
|||
```python |
|||
# urllib with python 2.x: |
|||
import urllib |
|||
urllib.urlopen("PING_URL") |
|||
``` |
|||
|
|||
You can include additional diagnostic information in the in the request body (for POST requests), or in the "User-Agent" request header: |
|||
|
|||
```python |
|||
# Passing diagnostic information in the POST body: |
|||
import requests |
|||
requests.post("PING_URL", data="temperature=-7") |
|||
``` |
|||
|
|||
```python |
|||
# Passing diagnostic information in the User-Agent header: |
|||
import requests |
|||
requests.get("PING_URL", headers={"User-Agent": "temperature=-7"}) |
|||
``` |
@ -0,0 +1,7 @@ |
|||
<h1>Ruby</h1> |
|||
<p>Below is an example of making a HTTP request to SITE_NAME from Ruby.</p> |
|||
<div class="highlight"><pre><span></span><span class="nb">require</span> <span class="s1">'net/http'</span> |
|||
<span class="nb">require</span> <span class="s1">'uri'</span> |
|||
|
|||
<span class="no">Net</span><span class="o">::</span><span class="no">HTTP</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="no">URI</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="s1">'PING_URL'</span><span class="p">))</span> |
|||
</pre></div> |
@ -0,0 +1,10 @@ |
|||
# Ruby |
|||
|
|||
Below is an example of making a HTTP request to SITE_NAME from Ruby. |
|||
|
|||
```ruby |
|||
require 'net/http' |
|||
require 'uri' |
|||
|
|||
Net::HTTP.get(URI.parse('PING_URL')) |
|||
``` |
@ -0,0 +1,24 @@ |
|||
<h1>Signalling failures</h1> |
|||
<p>Append <code>/fail</code> to a ping URL and use it to actively signal a failure. |
|||
Requesting the <code>/fail</code> URL will immediately mark the check as "down". |
|||
You can use this feature to minimize the delay from your monitored service failing |
|||
to you getting a notification.</p> |
|||
<p>Below is a skeleton code example in Python which signals a failure when the |
|||
work function returns an unexpected value or throws an exception:</p> |
|||
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">requests</span> |
|||
<span class="n">URL</span> <span class="o">=</span> <span class="s2">"PING_URL"</span> |
|||
|
|||
<span class="k">def</span> <span class="nf">do_work</span><span class="p">():</span> |
|||
<span class="c1"># Do your number crunching, backup dumping, newsletter sending work here.</span> |
|||
<span class="c1"># Return a truthy value on success.</span> |
|||
<span class="c1"># Return a falsy value or throw an exception on failure.</span> |
|||
<span class="k">return</span> <span class="bp">True</span> |
|||
|
|||
<span class="n">success</span> <span class="o">=</span> <span class="bp">False</span> |
|||
<span class="k">try</span><span class="p">:</span> |
|||
<span class="n">success</span> <span class="o">=</span> <span class="n">do_work</span><span class="p">()</span> |
|||
<span class="k">finally</span><span class="p">:</span> |
|||
<span class="c1"># On success, requests PING_URL</span> |
|||
<span class="c1"># On failure, requests PING_URL/fail</span> |
|||
<span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">URL</span> <span class="k">if</span> <span class="n">success</span> <span class="k">else</span> <span class="n">URL</span> <span class="o">+</span> <span class="s2">"/fail"</span><span class="p">)</span> |
|||
</pre></div> |
@ -0,0 +1,28 @@ |
|||
# Signalling failures |
|||
|
|||
Append `/fail` to a ping URL and use it to actively signal a failure. |
|||
Requesting the `/fail` URL will immediately mark the check as "down". |
|||
You can use this feature to minimize the delay from your monitored service failing |
|||
to you getting a notification. |
|||
|
|||
Below is a skeleton code example in Python which signals a failure when the |
|||
work function returns an unexpected value or throws an exception: |
|||
|
|||
```python |
|||
import requests |
|||
URL = "PING_URL" |
|||
|
|||
def do_work(): |
|||
# Do your number crunching, backup dumping, newsletter sending work here. |
|||
# Return a truthy value on success. |
|||
# Return a falsy value or throw an exception on failure. |
|||
return True |
|||
|
|||
success = False |
|||
try: |
|||
success = do_work() |
|||
finally: |
|||
# On success, requests PING_URL |
|||
# On failure, requests PING_URL/fail |
|||
requests.get(URL if success else URL + "/fail") |
|||
``` |
@ -0,0 +1,3 @@ |
|||
<li{% if slug == section %} class="active"{% endif %}> |
|||
<a href="{% url 'hc-serve-doc' slug %}">{{ title }}</a> |
|||
</li> |
@ -0,0 +1,22 @@ |
|||
{% extends "front/base_docs.html" %} |
|||
{% load compress static hc_extras %} |
|||
|
|||
{% block title %}Documentation - {% site_name %}{% endblock %} |
|||
{% block description %} |
|||
<meta name="description" content="Monitor any service that can make a HTTP request or send an email: cron jobs, Bash scripts, Python, Ruby, Node, PHP, JS, ..."> |
|||
{% endblock %} |
|||
{% block keywords %} |
|||
<meta name="keywords" content="healthchecks, crontab monitoring, python health check, bash health check, cron monitoring, cron tutorial, cron howto, api health check, open source"> |
|||
{% endblock %} |
|||
|
|||
|
|||
{% block docs_content %}<div class="docs-content">{{ content|safe }}</div>{% endblock %} |
|||
|
|||
{% block scripts %} |
|||
{% compress js %} |
|||
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script> |
|||
<script src="{% static 'js/bootstrap.min.js' %}"></script> |
|||
<script src="{% static 'js/clipboard.min.js' %}"></script> |
|||
<script src="{% static 'js/snippet-copy.js' %}"></script> |
|||
{% endcompress %} |
|||
{% endblock %} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue