Posted on
Artificial Intelligence

Build Artificial Intelligence Automation with Python and Bash

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Build Artificial Intelligence Automation with Python and Bash

What if your server could write your on‑call summary, categorize alerts, or draft incident tickets before you even wake up? You don’t need a new microservice platform to get there—just Bash to orchestrate, Python to think, and an LLM API to add brains.

This article shows how to wire Python and Bash into compact, reliable AI automations you can run anywhere Linux runs.

  • Problem: Many ops/dev tasks are repetitive (log triage, changelog drafts, status summaries), but stitching tools and APIs together is painful.

  • Value: Bash is unbeatable for glue and scheduling; Python is great for structured data and HTTP; LLMs excel at summarizing, classifying, and generating text. Together they’re a fast, portable way to ship useful automations.

Why Python + Bash + AI works

  • CLI-first and composable: Pipe anything into a Python helper that talks to an LLM, then pipe results to Slack/email/files.

  • Portable: Ships as a few scripts; runs under cron or systemd timers on any distro.

  • Observable and secure: Log to stdout/syslog; keep API keys in env files with strict permissions.

  • Cost- and time-efficient: Let the AI summarize/filter; keep the rest as simple shell pipelines you already know.

1) Install prerequisites

We’ll use Python (with a virtual environment), curl for HTTP, and jq for JSON handling in shell. Also install cron/cronie if you’ll schedule jobs with cron.

Debian/Ubuntu (apt):

sudo apt update
sudo apt install -y python3 python3-venv python3-pip curl jq git cron
sudo systemctl enable --now cron

Fedora/RHEL/CentOS Stream (dnf):

sudo dnf install -y python3 python3-pip curl jq git cronie
# venv is built into Python 3 on Fedora/RHEL
sudo systemctl enable --now crond

openSUSE (zypper):

sudo zypper refresh
sudo zypper install -y python3 python3-pip curl jq git cronie
sudo systemctl enable --now cron || sudo systemctl enable --now crond

Create a project folder and a Python virtual environment:

mkdir -p ~/ai-automation && cd ~/ai-automation
python3 -m venv .venv
. .venv/bin/activate
pip install --upgrade pip requests

2) Scaffold: environment and structure

  • Keep secrets in environment variables or an env file with 600 permissions.

  • Put small, single-purpose scripts under a scripts/ directory.

mkdir -p scripts
cat > .env <<'EOF'
AI_API_URL=https://api.openai-compatible.example/v1/chat/completions
AI_API_KEY=replace-me
AI_MODEL=gpt-4o-mini
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXXX/XXXX/XXXX
EOF
chmod 600 .env

3) A minimal Python “AI helper” you can pipe into

This script reads text from stdin, calls an OpenAI-compatible chat completion endpoint, and returns a concise summary. It’s generic: point it at any OpenAI-compatible server.

Save as scripts/ai_summarize.py:

#!/usr/bin/env python3
import os, sys, json, textwrap
import requests

API_URL  = os.getenv("AI_API_URL")
API_KEY  = os.getenv("AI_API_KEY")
MODEL    = os.getenv("AI_MODEL", "gpt-4o-mini")
TIMEOUT  = int(os.getenv("AI_TIMEOUT", "30"))

def main():
    if not API_URL or not API_KEY:
        print("Missing AI_API_URL or AI_API_KEY", file=sys.stderr)
        sys.exit(2)

    content = sys.stdin.read().strip()
    if not content:
        print("No input provided on stdin", file=sys.stderr)
        sys.exit(1)

    prompt = textwrap.dedent(f"""
    You are a precise ops assistant. Summarize the following text into:
    - Key events
    - Errors or anomalies
    - Top 3 actionable next steps
    Keep it under 180 words. Text:
    {content}
    """)

    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }
    payload = {
        "model": MODEL,
        "messages": [
            {"role": "system", "content": "You are a helpful, concise assistant for DevOps summaries."},
            {"role": "user", "content": prompt}
        ],
        "temperature": 0.2
    }

    try:
        r = requests.post(API_URL, headers=headers, json=payload, timeout=TIMEOUT)
        r.raise_for_status()
    except Exception as e:
        print(f"Request failed: {e}", file=sys.stderr)
        sys.exit(3)

    data = r.json()
    # OpenAI-compatible shape
    try:
        summary = data["choices"][0]["message"]["content"]
    except Exception:
        print(json.dumps(data, indent=2))
        sys.exit(4)

    print(summary.strip())

if __name__ == "__main__":
    main()

Make it executable:

chmod +x scripts/ai_summarize.py

4) Real-world example: hourly NGINX log summaries to Slack

This Bash script collects the last hour of NGINX logs, asks the AI for a short summary, and posts it to Slack. It falls back between journalctl and access.log based on what’s available.

Save as scripts/nginx_hourly_summary.sh:

#!/usr/bin/env bash
set -euo pipefail

# Load environment (API keys, Slack webhook)
if [ -f "$(dirname "$0")/../.env" ]; then
  set -a
  . "$(dirname "$0")/../.env"
  set +a
fi

# Collect last hour of logs
LOG_DATA=""
if command -v journalctl >/dev/null 2>&1 && systemctl list-units --type=service | grep -q nginx; then
  LOG_DATA="$(journalctl -u nginx --since '1 hour ago' --no-pager || true)"
elif [ -f /var/log/nginx/access.log ]; then
  LOG_DATA="$(awk -v d1="$(date -u -d '1 hour ago' +'%d/%b/%Y:%H')" '$4 ~ d1 {print}' /var/log/nginx/access.log || tail -n 200 /var/log/nginx/access.log)"
else
  echo "No NGINX logs found via journalctl or /var/log/nginx/access.log" >&2
  exit 0
fi

# Pre-trim to keep tokens reasonable
TRIMMED="$(echo "$LOG_DATA" | tail -n 400)"

# Summarize with Python helper
SUMMARY="$(printf "%s" "$TRIMMED" | "$(dirname "$0")/ai_summarize.py" || echo "Summary unavailable")"

echo "----- NGINX Hourly Summary -----"
echo "$SUMMARY"

# Optional: post to Slack
if [ -n "${SLACK_WEBHOOK_URL:-}" ]; then
  payload=$(jq -nc --arg text "*NGINX summary (last hour)*\n$SUMMARY" '{text: $text}')
  curl -fsS -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK_URL" || true
fi

Make it executable:

chmod +x scripts/nginx_hourly_summary.sh

Test it once:

. .env
./scripts/nginx_hourly_summary.sh

5) Schedule it (cron or systemd timers)

Option A: cron (simple and distro-agnostic)

crontab -e
# Add:
0 * * * * cd $HOME/ai-automation && . .venv/bin/activate && ./scripts/nginx_hourly_summary.sh >> $HOME/ai-automation/summary.log 2>&1

Option B: systemd timer (more control/visibility)

unit: ~/.config/systemd/user/nginx-summary.service

[Unit]
Description=NGINX hourly AI summary

[Service]
Type=oneshot
WorkingDirectory=%h/ai-automation
EnvironmentFile=%h/ai-automation/.env
ExecStart=%h/ai-automation/.venv/bin/bash -lc '%h/ai-automation/scripts/nginx_hourly_summary.sh'

timer: ~/.config/systemd/user/nginx-summary.timer

[Unit]
Description=Run NGINX summary hourly

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target

Enable and start:

systemctl --user daemon-reload
systemctl --user enable --now nginx-summary.timer
systemctl --user list-timers | grep nginx-summary

Extra tips for production hardening

  • Constrain input size: tail or sample to keep token usage and latency low.

  • Retries and fallbacks: wrap the Python call with basic retries; cache last good summary if the API is down.

  • Secrets: keep .env mode 600; or use systemd’s EnvironmentFile with restricted perms; never commit keys.

  • Observability: log to a file or journald; add exit codes and lightweight metrics (count summaries, failures).

  • Cost guardrails: limit frequency, cap bytes piped to the AI helper, or run on-demand during incidents.

Other easy wins to build next

  • Daily “release notes” from recent git commits:

    git log --since="yesterday" --pretty=format:'%h %s' \
    | ./scripts/ai_summarize.py \
    | mail -s "Daily Release Notes" you@example.com
    
  • Auto-triage long-running processes:

    ps aux --sort=-%mem | head -n 50 | ./scripts/ai_summarize.py
    
  • Classify alerts and propose next steps:

    tail -n 200 /var/log/syslog | ./scripts/ai_summarize.py
    

Conclusion / Call to Action

You now have a tiny, portable pattern for AI-powered automation: Bash to gather and route, Python to call an LLM, and cron/systemd to keep it running. Start with one pain point—like hourly log summaries—then iterate. Clone this scaffold into your ops repo, add a second helper for classification or templated replies, and watch the noise drop.

Your next step:

  • Install the prerequisites, paste in the two scripts, set your AI endpoint/key, and run a test.

  • Expand to another source (syslog, app logs, git, metrics).

  • Add guardrails (input caps, retries) and make it part of your daily toolkit.

Small scripts. Big leverage.