- Posted on
- • Artificial Intelligence
Artificial Intelligence Linux Maintenance Workflows
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Linux Maintenance Workflows (With Bash You Can Trust)
You don’t need a 2 a.m. incident to learn this lesson: most Linux maintenance is repetitive, noisy, and time-sensitive. Logs explode, patches pile up, config drift creeps in. Artificial Intelligence can turn that firehose into a focused checklist—if you wire it into trustworthy Bash workflows that validate changes before they touch production.
This article shows how to add AI to your Linux maintenance toolkit without surrendering safety. You’ll get practical Bash snippets for log triage, update briefings, config hardening with guardrails, and a simple scheduler to glue it together.
Why this is worth your time
AI is great at pattern recognition and summarization. That’s perfect for messy logs, change notes, and “what’s changed?” questions.
Linux maintenance needs determinism. We’ll keep AI advice in a sandbox: lint, test, diff, and only then apply.
You can run AI locally (Ollama) or via an OpenAI-compatible API—your choice, same scripts.
Prerequisites
Install core tools. Pick the command set for your distro.
Debian/Ubuntu (apt)
sudo apt update sudo apt install -y curl jq shellcheck shfmt cron python3-pip pipx gitFedora/RHEL/CentOS Stream (dnf)
sudo dnf install -y curl jq ShellCheck shfmt cronie python3-pip pipx git sudo systemctl enable --now crondopenSUSE/SLES (zypper)
sudo zypper refresh sudo zypper install -y curl jq ShellCheck shfmt cron python3-pip pipx git sudo systemctl enable --now cron
Optional AI backends:
OpenAI-compatible API
# Set your API key in your shell profile (~/.bashrc or /etc/profile.d/) export OPENAI_API_KEY="sk-..." export OPENAI_MODEL="gpt-4o-mini" # or another model your provider supports # Optional: point to a self-hosted OpenAI-compatible gateway # export OPENAI_BASE_URL="https://your-proxy.example.com/v1"Local AI via Ollama (Linux x86_64/ARM64)
curl -fsSL https://ollama.com/install.sh | sh sudo systemctl enable --now ollama ollama pull llama3 # Optional default model: export OLLAMA_MODEL="llama3"Note: Ollama uses its own installer; it is not installed via apt/dnf/zypper.
A reusable ai_ask function for Bash
Drop this into ~/.bashrc or a shared script (e.g., /usr/local/lib/ai-lib.sh). It will use Ollama locally if available or fall back to an OpenAI-compatible API.
#!/usr/bin/env bash
# /usr/local/lib/ai-lib.sh
set -Eeuo pipefail
ai_ask() {
local prompt="$1"
# Prefer local Ollama if reachable
if pgrep -x ollama >/dev/null 2>&1 || curl -sSf http://127.0.0.1:11434/api/tags >/dev/null 2>&1; then
local ollama_model="${OLLAMA_MODEL:-llama3}"
curl -sS http://127.0.0.1:11434/api/generate \
-H 'Content-Type: application/json' \
-d "$(jq -n --arg model "$ollama_model" --arg prompt "$prompt" --argjson stream false \
'{model:$model,prompt:$prompt,stream:false}')" \
| jq -r '.response'
return
fi
# Otherwise use OpenAI-compatible API
if [ -n "${OPENAI_API_KEY:-}" ]; then
local base="${OPENAI_BASE_URL:-https://api.openai.com/v1}"
local model="${OPENAI_MODEL:-gpt-4o-mini}"
curl -sS "$base/chat/completions" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg model "$model" --arg prompt "$prompt" \
'{model:$model,messages:[{role:"user",content:$prompt}],temperature:0.2}')" \
| jq -r '.choices[0].message.content'
else
echo "No AI backend configured. Set OPENAI_API_KEY or run ollama." >&2
return 1
fi
}
Source it where needed:
source /usr/local/lib/ai-lib.sh
1) AI-assisted log triage you can rely on
Goal: collapse 24h of noisy logs into a prioritized, actionable summary.
#!/usr/bin/env bash
# /usr/local/bin/ai-log-summarize
set -Eeuo pipefail
source /usr/local/lib/ai-lib.sh
collect_logs() {
if command -v journalctl >/dev/null 2>&1; then
{
echo "=== journalctl (err/warn, last 24h) ==="
journalctl -p 3..4 -S "24 hours ago" --no-pager -o short-iso || true
echo
echo "=== kernel dmesg (err/warn) ==="
dmesg --color=never --level=err,warn || true
} 2>/dev/null
else
{
echo "=== /var/log/syslog or messages (last 2000 lines) ==="
tail -n 2000 /var/log/syslog 2>/dev/null || tail -n 2000 /var/log/messages 2>/dev/null || true
echo
echo "=== kernel dmesg (err/warn) ==="
dmesg --color=never --level=err,warn || true
} 2>/dev/null
fi
}
main() {
local raw logs clipped prompt
raw="$(collect_logs)"
# Clip to ~16KB to keep prompts manageable
clipped="$(printf '%s' "$raw" | head -c 16000)"
prompt="$(cat <<'P'
You are a Linux SRE assistant. Given the following logs from the last day:
- Identify the top 5 issues by impact (outages, data loss, security first).
- For each, propose 1–2 precise next actions with relevant commands.
- Note any recurring patterns (flapping services, disk I/O, OOM, auth failures).
- Output in short bullets; include commands only when deterministic.
Logs:
P
)"
ai_ask "$prompt
$clipped"
}
main "$@"
Run:
sudo /usr/local/bin/ai-log-summarize
Tip: Pipe output into a ticket or paste into your incident doc. Keep the raw logs available for auditing.
2) Update and CVE impact brief before you patch
Goal: get a risk-aware summary of pending updates, across apt/dnf/zypper.
#!/usr/bin/env bash
# /usr/local/bin/ai-update-brief
set -Eeuo pipefail
source /usr/local/lib/ai-lib.sh
list_updates() {
if command -v apt >/dev/null 2>&1; then
echo "=== apt upgradable ==="
apt list --upgradable 2>/dev/null || true
echo
echo "=== apt security (from changelogs if available) ==="
apt-get -s upgrade | sed -n '1,200p' || true
elif command -v dnf >/dev/null 2>&1; then
echo "=== dnf check-update (all) ==="
dnf -q check-update || true
echo
echo "=== dnf security advisories ==="
dnf -q updateinfo list security all || true
elif command -v zypper >/dev/null 2>&1; then
echo "=== zypper list updates ==="
zypper --non-interactive lu || true
echo
echo "=== zypper list patches (security) ==="
zypper --non-interactive lp -s || true
else
echo "No supported package manager found." >&2
return 1
fi
}
main() {
local updates prompt
updates="$(list_updates | head -c 20000)"
prompt="$(cat <<'P'
You are reviewing pending Linux package updates.
- Group by severity (security/critical/high availability).
- Flag kernel, glibc, OpenSSH, OpenSSL, container runtime, and database updates.
- Note any likely reboots/restarts required.
- Output a short bulleted plan: what to patch first, and safely in what order.
Updates:
P
)"
ai_ask "$prompt
$updates"
}
main "$@"
Run:
/usr/local/bin/ai-update-brief
Still verify with your change window/process—AI is advisory, not authoritative.
3) Safer config hardening with AI + validation (example: sshd)
Never apply AI-generated configs blindly. Validate, diff, and have a rollback path.
#!/usr/bin/env bash
# /usr/local/bin/ai-sshd-harden
set -Eeuo pipefail
source /usr/local/lib/ai-lib.sh
CONF="/etc/ssh/sshd_config"
BACKUP="/etc/ssh/sshd_config.bak.$(date +%F-%H%M%S)"
CANDIDATE="/etc/ssh/sshd_config.ai"
require_root() { [ "$(id -u)" -eq 0 ] || { echo "Run as root."; exit 1; }; }
generate_candidate() {
local current prompt newconf
current="$(sed -e 's/[[:space:]]\+$//' "$CONF")"
prompt="$(cat <<'P'
You are a Linux hardening assistant. Propose a hardened OpenSSH sshd_config based on the current file.
Constraints:
- Keep syntax valid for OpenSSH (testable with: sshd -t -f <file>).
- Do NOT remove existing ListenAddress or Include directives.
- Prefer: Protocol 2; disable root login; disable password auth if keys present; limit auth tries; sane ciphers/MACs/Kex; log verbosity INFO.
- Keep comments explaining changes.
- Preserve functionality for remote admin (do not lock out existing key-based users).
Return only the full sshd_config text.
Current sshd_config:
P
)"
newconf="$(ai_ask "$prompt
$current")"
printf '%s\n' "$newconf" >"$CANDIDATE"
}
validate_and_apply() {
echo "Validating candidate with sshd -t..."
if ! sshd -t -f "$CANDIDATE" 2>&1 | tee /dev/stderr; then
echo "Validation failed. Not applying."
exit 2
fi
echo "Diff (candidate vs current):"
diff -u "$CONF" "$CANDIDATE" || true
read -r -p "Apply candidate? This will back up the current file to $BACKUP [y/N]: " ans
if [[ "${ans:-N}" =~ ^[Yy]$ ]]; then
cp -a "$CONF" "$BACKUP"
install -m 600 "$CANDIDATE" "$CONF"
systemctl reload sshd || systemctl restart sshd
echo "Applied. If you lose access, revert with: cp -a $BACKUP $CONF && systemctl restart sshd"
else
echo "Not applied."
fi
}
require_root
generate_candidate
validate_and_apply
Safety tips:
Test from a second session so you don’t lock yourself out.
Keep a screen/tmux session ready to revert quickly.
Use Include directories if your distro supports them to isolate AI changes.
4) Let AI draft Bash, but enforce a safety harness
Have AI generate a script, then automatically lint (ShellCheck), format (shfmt), and require explicit approval before running.
#!/usr/bin/env bash
# /usr/local/bin/ai-bash-draft
set -Eeuo pipefail
source /usr/local/lib/ai-lib.sh
PROMPT_FILE="${1:-}"
[ -n "$PROMPT_FILE" ] || { echo "Usage: ai-bash-draft <prompt.txt>"; exit 1; }
DRAFT="/tmp/ai-draft-$$.sh"
prompt="$(cat <<'P'
Write a portable Bash script that:
- Uses: set -Eeuo pipefail
- Has clear usage/help (-h)
- Accepts arguments safely (getopts)
- Avoids destructive actions unless --apply is given
- Prints what it would do in dry-run mode by default
Return only the script between triple backticks.
P
)"
user_req="$(cat "$PROMPT_FILE")"
resp="$(ai_ask "$prompt
User request:
$user_req")"
# Extract code between ``` blocks, else use whole response
code="$(printf '%s' "$resp" | awk '
/```/ {b=!b;next} b {print}
')"
if [ -z "$code" ]; then code="$resp"; fi
printf '%s\n' "$code" >"$DRAFT"
chmod +x "$DRAFT"
echo "Linting with ShellCheck..."
if ! shellcheck "$DRAFT"; then
echo "ShellCheck found issues. Review $DRAFT"
exit 2
fi
echo "Formatting with shfmt..."
shfmt -w "$DRAFT" || true
echo "Draft ready: $DRAFT"
echo "Review, then run explicitly: $DRAFT --help"
This pattern catches many footguns before they run on your system.
5) Wire it together in a daily report
Create a lightweight daily report of logs and updates.
#!/usr/bin/env bash
# /usr/local/bin/ai-maint-report
set -Eeuo pipefail
mkdir -p /var/log/ai-maint
TS="$(date +%F)"
OUT="/var/log/ai-maint/$TS.txt"
{
echo "=== AI Maintenance Report ($TS) ==="
echo
echo "[1/2] Log summary:"
/usr/local/bin/ai-log-summarize || echo "(log summary failed)"
echo
echo "[2/2] Update brief:"
/usr/local/bin/ai-update-brief || echo "(update brief failed)"
} | tee "$OUT"
Cron it:
Debian/Ubuntu (cron)
sudo bash -c 'echo "15 07 * * * root /usr/local/bin/ai-maint-report >/var/log/ai-maint/cron.log 2>&1" >/etc/cron.d/ai-maint' sudo systemctl restart cronFedora/RHEL/CentOS (cronie)
sudo bash -c 'echo "15 07 * * * root /usr/local/bin/ai-maint-report >/var/log/ai-maint/cron.log 2>&1" >/etc/cron.d/ai-maint' sudo systemctl restart crondopenSUSE/SLES (cron)
sudo bash -c 'echo "15 07 * * * root /usr/local/bin/ai-maint-report >/var/log/ai-maint/cron.log 2>&1" >/etc/cron.d/ai-maint' sudo systemctl restart cron
Prefer systemd timers in production? Convert the script to a oneshot service + timer.
Real-world notes and gotchas
Token discipline: trim inputs (head -c) and keep prompts tight to avoid slow, costly calls.
Validation first: always test configs (e.g., sshd -t) and lint generated scripts.
Provenance: save AI outputs and diffs alongside tickets for later audits.
Local vs. cloud: use Ollama on hosts without egress; use API providers where latency and model quality matter most.
Conclusion and next step
AI won’t replace your Linux fundamentals—it amplifies them. Start by:
Installing the prerequisites and setting up ai_ask.
Running ai-log-summarize and ai-update-brief on a non-critical host.
Trying ai-sshd-harden, but only with validation and backups.
Scheduling ai-maint-report to get a daily pulse.
If this improved your signal-to-noise ratio, standardize it: put these scripts in your config management, add a systemd timer, and tailor the prompts to your environment. Your 2 a.m. self will thank you.