- Posted on
- • Artificial Intelligence
Artificial Intelligence Log File Analysis
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Log File Analysis with Bash: From Grep to “Aha!”
If you’ve ever tailed 10,000 lines of syslog at 3 AM hoping to spot the one line that matters, this post is for you. Traditional bash tools like grep, awk, and journalctl are amazing, but they’re manual and reactive. AI-driven log analysis augments your command line: it learns what “normal” looks like and surfaces what’s new, rare, or risky—fast.
In this article you’ll:
Understand why AI fits log analysis so well.
Set up a minimal, private, open-source toolchain on Linux.
Build a pipeline to normalize, learn from, and detect anomalies in logs.
Automate and alert using Bash.
See real-world examples you can reproduce today.
Why AI for logs?
Logs are semi-structured and repetitive. Template mining (like Drain/Drain3) automatically groups similar lines into patterns, stripping volatile details (PIDs, IPs, counters). This yields cleaner “events” you can reason about.
Unsupervised anomaly detection can flag never-before-seen templates and unexpected spikes without labeled data.
It’s compute-light and runs locally. No need to ship your logs to a third party—great for privacy and regulated environments.
It complements, not replaces,
grep. Use bash for what it’s great at, and let AI do the tedious pattern-learning.
What we’ll build
- A bash-centric workflow that: 1) Collects and normalizes logs. 2) Learns log templates from your historical data. 3) Detects new/rare patterns and spikes in fresh logs. 4) Alerts you via email, all offline and on your own box.
We’ll use Python’s Drain3 for template mining. Optional: add classic ML (e.g., PCA from Loglizer) later if you want more sophistication.
1) Install prerequisites
We’ll need Python 3, virtual environments, compilers for some scientific packages, and an email client for alerts. Choose your package manager:
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y python3 python3-venv python3-pip python3-dev build-essential gcc g++ \
git jq sed grep coreutils bsd-mailx
- Fedora/RHEL/CentOS (dnf):
sudo dnf install -y python3 python3-pip python3-virtualenv python3-devel gcc gcc-c++ \
git jq sed grep coreutils mailx
- openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y python3 python3-pip python3-virtualenv python3-devel gcc gcc-c++ \
git jq sed grep coreutils s-nail
Create a virtual environment and install Python libraries:
python3 -m venv ~/.venvs/logai
source ~/.venvs/logai/bin/activate
pip install --upgrade pip
pip install drain3 numpy scipy scikit-learn
Note: Drain3 provides online log template mining. NumPy/SciPy/Scikit-learn are optional but handy if you extend this with classic ML.
2) Collect and normalize logs
AI works best on consistent inputs. Normalize PIDs, IPs, hex addresses, and numbers while preserving timestamps and message structure. Here’s a small normalizer you can reuse:
cat > normalize.sh << 'EOF'
#!/usr/bin/env bash
# Normalize logs: keep ISO timestamp and unit name if present; anonymize volatile fields.
# Usage: journalctl ... | ./normalize.sh
# Or: cat /var/log/nginx/access.log | ./normalize.sh
# Read from stdin, output to stdout
# Heuristics: replace IPv4/IPv6, long hex, and numbers with tokens after timestamp.
awk '
{
line=$0
# Extract ISO-like timestamp if present (journalctl -o short-iso)
ts=""
if (match(line, /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:.+-Z]+/)) {
ts=substr(line, RSTART, RLENGTH)
rest=substr(line, RLENGTH+2) # skip space
} else {
rest=line
}
# Anonymize common volatile bits in "rest"
# IPv4
gsub(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/, "<IP>", rest)
# IPv6 (simplified)
gsub(/[0-9a-fA-F:]{2,}:[0-9a-fA-F:]+/, "<IP6>", rest)
# Long hex (addresses, hashes)
gsub(/[0-9a-fA-F]{8,}/, "<HEX>", rest)
# Standalone numbers (ports, PIDs, counters)
gsub(/[0-9]+/, "<NUM>", rest)
if (ts != "")
print ts " " rest
else
print rest
}'
EOF
chmod +x normalize.sh
Examples:
- Journald unit (last 24h, ISO timestamps):
sudo journalctl -u ssh -S "24 hours ago" -o short-iso | ./normalize.sh > data/ssh_24h.norm
- Nginx access logs:
sudo cat /var/log/nginx/access.log | ./normalize.sh > data/nginx.norm
Tip: Start with a baseline set of “healthy” logs to train on.
3) Learn templates (unsupervised)
Train a template miner on your normalized, mostly-healthy history. Drain3 persists learned clusters so you can reuse them later.
mkdir -p model data
cat > ai-log-train.py << 'EOF'
#!/usr/bin/env python3
import sys, os, json
from drain3 import TemplateMiner
from drain3.file_persistence import FilePersistence
# Where to store model and baseline frequencies
os.makedirs("model", exist_ok=True)
persistence = FilePersistence("model/drain3_state.json")
tm = TemplateMiner(persistence=persistence)
freq = {}
total = 0
for line in sys.stdin:
msg = line.strip()
if not msg:
continue
r = tm.add_log_message(msg)
tid = r["cluster_id"]
freq[tid] = freq.get(tid, 0) + 1
total += 1
# Save simple baseline frequencies and totals
with open("model/baseline_freqs.json", "w") as f:
json.dump({"total": total, "freq": freq}, f)
print(f"Trained on {total} lines; templates: {len(freq)}")
EOF
chmod +x ai-log-train.py
Train with your normalized files:
# Example: combine multiple healthy sources
cat data/ssh_24h.norm data/nginx.norm | ./ai-log-train.py
What you get:
model/drain3_state.jsonholds learned templates.model/baseline_freqs.jsonstores how frequent each template was during training.
4) Detect anomalies in fresh logs
We’ll flag:
New/unseen templates (structural anomalies).
Significant frequency spikes vs. baseline (volume anomalies, rough z-score approximation).
cat > ai-log-detect.py << 'EOF'
#!/usr/bin/env python3
import sys, os, json, math, time
from drain3 import TemplateMiner
from drain3.file_persistence import FilePersistence
os.makedirs("model", exist_ok=True)
persistence = FilePersistence("model/drain3_state.json")
tm = TemplateMiner(persistence=persistence)
# Load baseline frequencies
baseline = {"total": 0, "freq": {}}
try:
with open("model/baseline_freqs.json") as f:
baseline = json.load(f)
except FileNotFoundError:
pass
window_freq = {}
start = time.time()
def z_score(curr, base, total_curr, total_base, eps=1e-9):
# Scale baseline to current window size, then compute a simple deviation ratio
# This is a crude stat; refine as needed.
if total_base == 0:
return float("inf")
rate_base = base / (total_base + eps)
exp = rate_base * total_curr
if exp < 5: # low expectation: treat spikes conservatively
return (curr - exp) / math.sqrt(exp + eps) if exp > 0 else float("inf")
return (curr - exp) / math.sqrt(exp + eps)
for line in sys.stdin:
msg = line.strip()
if not msg:
continue
r = tm.add_log_message(msg)
tid = r["cluster_id"]
change = r.get("change_type")
window_freq[tid] = window_freq.get(tid, 0) + 1
# Flag brand-new templates immediately
if change == "cluster_created":
print(f"[NEW-TEMPLATE]\t{msg}")
# After the stream ends, check for spikes
total_curr = sum(window_freq.values())
for tid, curr in window_freq.items():
base = baseline["freq"].get(tid, 0)
zs = z_score(curr, base, total_curr, baseline["total"])
# Heuristic thresholds: z > 4 or entirely absent in baseline
if base == 0 and curr >= 3:
print(f"[RARE-SPIKE]\tTemplate={tid}\tcount={curr}\t(no baseline)")
elif zs >= 4:
print(f"[FREQ-SPIKE]\tTemplate={tid}\tcount={curr}\tz≈{zs:.2f}")
EOF
chmod +x ai-log-detect.py
Run detection on new logs:
# Last hour of sshd logs
sudo journalctl -u ssh -S "1 hour ago" -o short-iso | ./normalize.sh | ./ai-log-detect.py
Optional: pipe anomalies into a file for alerting:
sudo journalctl -u nginx -S "10 min ago" -o short-iso \
| ./normalize.sh | ./ai-log-detect.py | tee /tmp/logai_alerts.txt
5) Automate and alert from Bash
A small wrapper runs detection on multiple sources and emails the results.
cat > run-logai.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
VENV="${HOME}/.venvs/logai"
ACT="${VENV}/bin/activate"
OUT="/tmp/logai_alerts.$(date +%s).txt"
: > "$OUT"
source "$ACT"
# Sources to check (customize to taste)
sudo journalctl -u ssh -S "30 min ago" -o short-iso \
| ./normalize.sh | ./ai-log-detect.py >> "$OUT"
sudo journalctl -u nginx -S "30 min ago" -o short-iso \
| ./normalize.sh | ./ai-log-detect.py >> "$OUT"
# File logs example
if [ -f /var/log/auth.log ]; then
sudo tail -n 5000 /var/log/auth.log \
| ./normalize.sh | ./ai-log-detect.py >> "$OUT"
fi
# Email if there are findings
if grep -qE "NEW-TEMPLATE|FREQ-SPIKE|RARE-SPIKE" "$OUT"; then
# Debian/Ubuntu: bsd-mailx; Fedora/RHEL: mailx; openSUSE: s-nail (mailx)
cat "$OUT" | mail -s "[logai] anomalies detected on $(hostname)" you@example.com
fi
echo "Results in $OUT"
EOF
chmod +x run-logai.sh
Schedule with cron:
( crontab -l 2>/dev/null; echo "*/15 * * * * /path/to/run-logai.sh" ) | crontab -
Tip: Re-train the baseline weekly during healthy periods so your model evolves. Keep the prior model around for rollbacks:
cp -r model "model.$(date +%F_%H%M%S)"
Real-world examples you can try
SSH brute force burst:
- Symptom: multiple “Failed password for invalid user …” lines in
sshd. - Effect: The detector flags either a new template variation or a frequency spike on the known template in the last 30 minutes.
- Symptom: multiple “Failed password for invalid user …” lines in
Nginx upstream failures:
- Symptom: “upstream prematurely closed connection” or surges in “499/500/502”.
- Effect: If verbiage changes (e.g., new upstream hostname pattern), you’ll see
[NEW-TEMPLATE]; otherwise a[FREQ-SPIKE]signals a sudden rise.
Disk I/O issues in dmesg/journald:
- Symptom: “I/O error, dev sda …” appears rarely in baselines.
- Effect: Quickly pops as a new or rare template, helping you catch hardware issues early.
To test, replay a sample:
# Simulate a burst by repeating a line
yes "2024-01-01T00:00:00Z sshd[<NUM>]: Failed password for invalid user <HEX> from <IP> port <NUM> ssh2" | head -n 200 \
| ./ai-log-detect.py
Optional: add classic ML (Loglizer)
Want PCA/invariant mining over event count vectors? Install Loglizer and experiment on top of the parsed templates:
source ~/.venvs/logai/bin/activate
pip install loglizer
You’ll convert template sequences to count vectors per window and apply PCA/IForest. This adds statistical depth when simple spikes aren’t enough.
Troubleshooting tips
Permission denied reading logs: prefix with
sudoor adjust group membership (e.g.,systemd-journal).Too many “NEW-TEMPLATE” hits: refine normalization (
normalize.sh) to replace more volatile tokens (request IDs, UUIDs).No anomalies but you feel something is off: shrink the time window or retrain baseline using a longer healthy period.
Email not sending: on Debian/Ubuntu install and configure
postfixor use an SMTP relay. For quick local testing, tryssmtpormsmtp.
Conclusion and next steps
AI-assisted log analysis doesn’t require shipping data to the cloud or a week-long SIEM rollout. With a few Bash commands and open-source libraries, you can:
Learn your system’s “normal”.
Get immediate signals for new or spiking events.
Automate alerts on a cadence that fits your ops tempo.
Next steps:
Point the pipeline at your most critical services.
Tune
normalize.shfor your environment (web apps, DBs, kernels).Retrain baselines regularly, version your models, and document what you consider “healthy”.
Extend with Loglizer or your favorite ML to score sessions and correlate across services.
When the next 3 AM page hits, you’ll have more than grep—you’ll have a model that already knows your logs.