diff --git a/run-analysis.sh b/run-analysis.sh index e487224..4149b9a 100755 --- a/run-analysis.sh +++ b/run-analysis.sh @@ -1,6 +1,15 @@ #!/usr/bin/env bash set -e +# Prevent concurrent executions of this script. +LOCK_FILE="/tmp/$(basename "$0").lock" +if [ -e "$LOCK_FILE" ]; then + echo "[WARN] $(basename "$0") is already running (lock file present)." >&2 + exit 0 +fi +touch "$LOCK_FILE" +trap 'rm -f "$LOCK_FILE"' EXIT + # Ensure virtual environment exists if [ ! -d ".venv" ]; then echo "[INFO] Creating virtual environment..." diff --git a/run-import.sh b/run-import.sh index 22b4b31..3c79d35 100755 --- a/run-import.sh +++ b/run-import.sh @@ -1,6 +1,17 @@ #!/usr/bin/env bash set -e +# Prevent multiple simultaneous runs by using a lock file specific to this +# script. If the lock already exists, assume another instance is running and +# exit gracefully. +LOCK_FILE="/tmp/$(basename "$0").lock" +if [ -e "$LOCK_FILE" ]; then + echo "[WARN] $(basename "$0") is already running (lock file present)." >&2 + exit 0 +fi +touch "$LOCK_FILE" +trap 'rm -f "$LOCK_FILE"' EXIT + # Ensure virtual environment exists if [ ! -d ".venv" ]; then echo "[INFO] Creating virtual environment..." diff --git a/run-reports.sh b/run-reports.sh index a0d718f..bfe736d 100755 --- a/run-reports.sh +++ b/run-reports.sh @@ -1,6 +1,15 @@ #!/usr/bin/env bash set -e +# Prevent concurrent executions of this script. +LOCK_FILE="/tmp/$(basename "$0").lock" +if [ -e "$LOCK_FILE" ]; then + echo "[WARN] $(basename "$0") is already running (lock file present)." >&2 + exit 0 +fi +touch "$LOCK_FILE" +trap 'rm -f "$LOCK_FILE"' EXIT + # Ensure virtual environment exists if [ ! -d ".venv" ]; then echo "[INFO] Creating virtual environment..." diff --git a/scripts/generate_reports.py b/scripts/generate_reports.py index 4b5692a..cf06398 100644 --- a/scripts/generate_reports.py +++ b/scripts/generate_reports.py @@ -161,7 +161,10 @@ def _generate_interval(interval: str, domain: Optional[str] = None) -> None: report_list.append(entry) _save_json(out_dir / "reports.json", report_list) - typer.echo(f"Generated {interval} reports") + if domain: + typer.echo(f"Generated {interval} reports for {domain}") + else: + typer.echo(f"Generated {interval} reports") def _generate_all_domains(interval: str) -> None: @@ -175,7 +178,7 @@ def _generate_root_index() -> None: intervals = [ p.name for p in OUTPUT_DIR.iterdir() - if p.is_dir() and p.name.lower() not in {"domains", "global", "analysis"} + if p.is_dir() and p.name.lower() not in {"domains", "global"} ] intervals.sort() diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..be5087c --- /dev/null +++ b/setup.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -e + +# Default schedules +import_sched="*/5 * * * *" +report_sched="0 * * * *" +analysis_sched="0 0 * * *" +remove=false + +usage() { + echo "Usage: $0 [--import CRON] [--reports CRON] [--analysis CRON] [--remove]" +} + +while [ $# -gt 0 ]; do + case "$1" in + --import) + import_sched="$2"; shift 2;; + --reports) + report_sched="$2"; shift 2;; + --analysis) + analysis_sched="$2"; shift 2;; + --remove) + remove=true; shift;; + -h|--help) + usage; exit 0;; + *) + usage; exit 1;; + esac +done + +repo_dir="$(cd "$(dirname "$0")" && pwd)" + +if [ "$remove" = true ]; then + tmp=$(mktemp) + sudo crontab -l 2>/dev/null | grep -v "# ngxstat import" | grep -v "# ngxstat reports" | grep -v "# ngxstat analysis" > "$tmp" || true + sudo crontab "$tmp" + rm -f "$tmp" + echo "[INFO] Removed ngxstat cron entries" + exit 0 +fi + +cron_entries="${import_sched} cd ${repo_dir} && ./run-import.sh # ngxstat import\n${report_sched} cd ${repo_dir} && ./run-reports.sh # ngxstat reports\n${analysis_sched} cd ${repo_dir} && ./run-analysis.sh # ngxstat analysis" + +( sudo crontab -l 2>/dev/null; echo -e "$cron_entries" ) | sudo crontab - + +echo "[INFO] Installed ngxstat cron entries" diff --git a/templates/index.html b/templates/index.html index 0a8abed..7b0b98f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -286,7 +286,7 @@ Object.entries(sections).forEach(([key, section]) => { section.classList.toggle('is-hidden', key !== name); }); - intervalControl.classList.toggle('is-hidden', name === 'overview' || name === 'analysis'); + intervalControl.classList.toggle('is-hidden', name === 'overview'); domainControl.classList.toggle('is-hidden', name !== 'domain'); if (name === 'overview') { loadStats(); diff --git a/tests/test_reports.py b/tests/test_reports.py index dbe71c2..fec898c 100644 --- a/tests/test_reports.py +++ b/tests/test_reports.py @@ -184,8 +184,6 @@ def test_generate_root_index(tmp_path, sample_reports, monkeypatch): (tmp_path / "output" / "domains" / "bar.com").mkdir(parents=True) # add an extra directory with capitalized name to ensure it's ignored (tmp_path / "output" / "Global").mkdir(parents=True) - # add an analysis directory to ensure it's excluded - (tmp_path / "output" / "analysis").mkdir(parents=True) gr._generate_root_index() @@ -198,7 +196,6 @@ def test_generate_root_index(tmp_path, sample_reports, monkeypatch): assert '