Monitor any command with periodic Slack, Discord, or email notifications
Project description
Job Monitor
A CLI tool that wraps any command (or attaches to a running process) and sends periodic notifications with job status, system resource usage, and recent terminal output. Supports Slack, Discord, and email backends.
Installation
From PyPI
pip install jobmonitor-cli
From source
# Create the conda environment
conda env create -f environment.yml
# Install the package
conda activate jobmonitor
pip install -e .
# (Optional) Make available system-wide for all users
sudo ln -s $(which jobmonitor) /usr/local/bin/jobmonitor
Backend Setup
You can configure backends via CLI flags, environment variables, or a config file (~/.jobmonitorrc). Priority: CLI flags > env vars > config file > defaults.
Slack (default)
- Go to api.slack.com/apps > Create New App > From scratch
- Go to Incoming Webhooks > Toggle On > Add New Webhook to Workspace
- Pick a channel and copy the webhook URL
- Add to your
~/.bashrc:
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
Discord
- In your Discord server, go to a channel's settings > Integrations > Webhooks > New Webhook
- Copy the webhook URL
- Add to your
~/.bashrc:
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/YOUR/WEBHOOK/URL"
Email uses SMTP to send notifications. If your machine has postfix or sendmail running, it works out of the box with localhost.
Add to your ~/.bashrc:
export JOBMONITOR_EMAIL_TO="you@example.com"
# Optional — defaults shown:
# export SMTP_SERVER="localhost"
For external SMTP (e.g., Gmail), set --smtp-server and --smtp-port flags. Note: Gmail requires an app password.
Changing the default backend
By default, jobmonitor uses Slack. To change the default, add to your ~/.bashrc:
export JOBMONITOR_BACKEND="discord" # or "email"
You can always override per-invocation with --backend.
Config File
Instead of environment variables, you can create ~/.jobmonitorrc to set persistent defaults:
[defaults]
backend = slack
interval = 2h
tail = 5
cpu = false
disk = false
no-gpu = false
no-ram = false
[slack]
webhook_url = https://hooks.slack.com/services/YOUR/WEBHOOK/URL
[discord]
webhook_url = https://discord.com/api/webhooks/YOUR/WEBHOOK/URL
[email]
to = you@example.com
from = jobmonitor@yourmachine
smtp_server = localhost
smtp_port = 25
All sections and keys are optional. CLI flags and environment variables always take priority over the config file.
Usage
Wrap a new command
jobmonitor --interval 2h --name "experiment-1" -- python train.py --epochs 100
jobmonitor --interval 1h --name "full-sweep" -- bash experiments.sh
# Tail a log file instead of stdout
jobmonitor --interval 2h --log path/to/logfile.log -- python train.py
# Using Discord
jobmonitor --backend discord --interval 2h -- python train.py
# Using email
jobmonitor --backend email --email-to user@example.com -- python train.py
Attach to an already-running process
# Find the PID
ps aux | grep train
# Attach to it
jobmonitor --pid 12345 --interval 2h --name "experiment-1"
# Optionally tail a log file for output context
jobmonitor --pid 12345 --interval 2h --log path/to/logfile.log
Options
| Flag | Default | Description |
|---|---|---|
--interval |
2h |
Notification interval (e.g. 30m, 1h30m, 2h) |
--backend |
slack |
Notification backend: slack, discord, or email |
--webhook-url |
config/env | Webhook URL for Slack or Discord |
--name |
auto | Job name shown in notifications |
--tail |
5 |
Number of recent output lines to include |
--pid |
- | Attach to an existing process by PID |
--log |
- | Log file to tail for notification output instead of stdout. Works in both wrap and --pid modes |
--no-gpu |
- | Skip GPU info in notifications |
--no-ram |
- | Skip RAM info in notifications |
--cpu |
- | Include CPU usage in notifications |
--disk |
- | Include disk usage in notifications |
--email-to |
config/env | Recipient email (email backend) |
--email-from |
user@hostname |
Sender email (email backend) |
--smtp-server |
localhost |
SMTP server (email backend) |
--smtp-port |
25 |
SMTP port (email backend) |
Notifications
Each notification includes:
- Job status (started / running / completed / failed / cancelled)
- Elapsed time
- Hostname
- RAM usage (unless
--no-ram) - GPU utilization, memory, and temperature (unless
--no-gpu) - CPU usage (opt-in with
--cpu) - Disk usage (opt-in with
--disk) - Last N lines of terminal output (or log file if
--logis set) - The command being monitored
A notification is sent immediately when monitoring begins, then at every --interval, and once more when the job finishes.
Running tests
conda activate jobmonitor
pytest tests/ -v
Publishing to PyPI
pip install build twine
python -m build
twine upload dist/*
Requires a PyPI account and API token.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jobmonitor_cli-0.1.2.tar.gz.
File metadata
- Download URL: jobmonitor_cli-0.1.2.tar.gz
- Upload date:
- Size: 16.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8971db460fe36fc243ae91686c19723c4a9957816143168643c23ec646726745
|
|
| MD5 |
83bfa1893097ac4844731ca91684706a
|
|
| BLAKE2b-256 |
5e3137ff65acdb1237dbfcb9aec89dffb19c1e310864043d2467901f0c1ec8b2
|
File details
Details for the file jobmonitor_cli-0.1.2-py3-none-any.whl.
File metadata
- Download URL: jobmonitor_cli-0.1.2-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e861202b62af2eb8351312f724062e69fc58477b20a83002a092dd9770aaef47
|
|
| MD5 |
431e47436525f418c93abe343e4ecc37
|
|
| BLAKE2b-256 |
491f418a4fb9f60c2225632600e9c3f379082c669e15c2f1ba9047734aee9905
|