Slack Bildirimi Gönderme: Webhook Entegrasyonu
Sistem yöneticilerinin en sık karşılaştığı sorunlardan biri şu: Bir şeyler bozulduğunda ya da önemli bir olay gerçekleştiğinde, doğru kişiye zamanında haber ulaştırmak. E-posta artık bu iş için çok yavaş. PagerDuty gibi araçlar ise küçük ekipler için fazla karmaşık ve pahalı olabiliyor. Slack webhook entegrasyonu tam bu noktada devreye giriyor: Birkaç satır kod ile sunucularınızdan, CI/CD pipeline’larınızdan veya herhangi bir script’ten doğrudan Slack kanalınıza mesaj gönderebilirsiniz.
Bu yazıda Slack Incoming Webhook yapısını sıfırdan kuracak, bash script’lerinden Python’a kadar farklı senaryolarda nasıl kullanacağınızı görecek ve gerçek dünya monitoring entegrasyonlarını ele alacağız.
Slack Webhook Nedir ve Nasıl Çalışır
Incoming Webhook, Slack’in dışarıdan mesaj almak için sağladığı bir HTTP endpoint’idir. Siz bu URL’ye bir POST isteği gönderirsiniz, Slack da mesajı belirlediğiniz kanala iletir. OAuth token’ı yönetmenize gerek yok, karmaşık bir API akışı yok. Sadece bir URL ve JSON payload yeterli.
Webhook URL’si şöyle görünür:
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Bu URL üç bölümden oluşuyor: workspace ID, channel ID ve güvenlik token’ı. Bu URL’yi kimseyle paylaşmayın, versiyon kontrolüne eklemeyin. Sızdırırsanız herkes sizin kanalınıza mesaj gönderebilir.
Webhook Oluşturma: Adım Adım
Önce Slack tarafında webhook’u oluşturmamız gerekiyor.
Adım 1: Slack App Oluşturma
- [api.slack.com/apps](https://api.slack.com/apps) adresine gidin
- “Create New App” butonuna tıklayın
- “From scratch” seçeneğini seçin
- App adı girin (örneğin: “ServerBot” veya “Infrastructure Alerts”)
- Workspace’inizi seçin
Adım 2: Incoming Webhooks’u Aktifleştirme
- Sol menüden “Incoming Webhooks” bölümüne girin
- Toggle’ı “On” pozisyonuna alın
- Sayfanın altına kaydırın ve “Add New Webhook to Workspace” butonuna tıklayın
- Hangi kanala mesaj göndereceğinizi seçin (örneğin: #alerts, #infrastructure)
- “Allow” butonuna tıklayın
Artık bir webhook URL’niz var. Bu URL’yi kopyalayıp güvenli bir yere kaydedin.
Adım 3: Test Edin
Hemen terminalden test edelim:
WEBHOOK_URL="https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX"
curl -X POST -H 'Content-type: application/json'
--data '{"text":"Merhaba! Bu bir test mesajidir."}'
"$WEBHOOK_URL"
Eğer Slack kanalınıza mesaj geldiyse, her şey çalışıyor demektir. ok cevabı aldıysanız istek başarılı olmuştur.
Temel Bash Script ile Bildirim Gönderme
Günlük sysadmin işlerinde en çok bash kullanacaksınız. İşte yeniden kullanılabilir bir Slack bildirim fonksiyonu:
#!/bin/bash
# Slack webhook URL'sini environment variable olarak tutun
SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:-}"
send_slack_message() {
local message="$1"
local channel="${2:-}" # Bos birakilirsa webhook'un varsayilan kanali kullanilir
local username="${3:-ServerBot}"
local emoji="${4:-:robot_face:}"
if [[ -z "$SLACK_WEBHOOK_URL" ]]; then
echo "HATA: SLACK_WEBHOOK_URL environment variable tanimli degil!" >&2
return 1
fi
local payload
payload=$(cat <<EOF
{
"username": "${username}",
"icon_emoji": "${emoji}",
"text": "${message}"
}
EOF
)
local response
response=$(curl -s -o /dev/null -w "%{http_code}"
-X POST
-H 'Content-type: application/json'
--data "$payload"
"$SLACK_WEBHOOK_URL")
if [[ "$response" != "200" ]]; then
echo "HATA: Slack mesaji gonderilemedi. HTTP kod: $response" >&2
return 1
fi
return 0
}
# Kullanim ornekleri
send_slack_message "Sunucu yedeklemesi tamamlandi."
send_slack_message ":warning: Disk dolulugu %85'i gecti!" "" "AlertBot" ":warning:"
send_slack_message ":white_check_mark: Deploy basariyla tamamlandi."
Bu fonksiyonu /etc/profile.d/slack_notify.sh dosyasına eklerseniz tüm scriptlerinizden çağırabilirsiniz.
Disk Alanı Monitörü: Gerçek Dünya Senaryosu
Pratik bir örnek yapalım. Disk kullanımı belirli bir eşiği aştığında otomatik Slack bildirimi gönderen script:
#!/bin/bash
# /usr/local/bin/disk_monitor.sh
# Cron ile her saat calistirin: 0 * * * * /usr/local/bin/disk_monitor.sh
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX"
HOSTNAME=$(hostname -f)
THRESHOLD=80
CRITICAL_THRESHOLD=90
send_alert() {
local mount_point="$1"
local usage_percent="$2"
local severity="$3"
local emoji color
if [[ "$severity" == "critical" ]]; then
emoji=":rotating_light:"
color="danger"
else
emoji=":warning:"
color="warning"
fi
local payload
payload=$(cat <<EOF
{
"attachments": [
{
"color": "${color}",
"title": "${emoji} Disk Alani Uyarisi - ${HOSTNAME}",
"fields": [
{
"title": "Sunucu",
"value": "${HOSTNAME}",
"short": true
},
{
"title": "Mount Point",
"value": "${mount_point}",
"short": true
},
{
"title": "Kullanim",
"value": "%${usage_percent}",
"short": true
},
{
"title": "Onem Seviyesi",
"value": "${severity^^}",
"short": true
}
],
"footer": "Disk Monitor",
"ts": $(date +%s)
}
]
}
EOF
)
curl -s -X POST
-H 'Content-type: application/json'
--data "$payload"
"$SLACK_WEBHOOK_URL" > /dev/null
}
# Disk kullanim kontrolu
while IFS= read -r line; do
usage=$(echo "$line" | awk '{print $5}' | tr -d '%')
mount=$(echo "$line" | awk '{print $6}')
if [[ "$usage" -ge "$CRITICAL_THRESHOLD" ]]; then
send_alert "$mount" "$usage" "critical"
elif [[ "$usage" -ge "$THRESHOLD" ]]; then
send_alert "$mount" "$usage" "warning"
fi
done < <(df -h | grep -v "^Filesystem" | grep -v "tmpfs")
Bu script’i crontab’a ekleyin:
# Her saat basi calistir
0 * * * * /usr/local/bin/disk_monitor.sh
# Ya da sudo ile
sudo crontab -e
Block Kit ile Zengin Mesajlar
Slack’in Block Kit formatını kullanarak çok daha okunaklı ve görsel mesajlar gönderebilirsiniz. Block Kit, mesajı bölümlere ayırmanıza, buton eklemenize ve bilgileri düzenli şekilde sunmanıza olanak tanıyor.
#!/bin/bash
# Deploy bildirimi - Block Kit kullanimi
SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL}"
DEPLOY_ENV="${1:-production}"
APP_NAME="${2:-myapp}"
VERSION="${3:-latest}"
DEPLOY_USER=$(whoami)
DEPLOY_TIME=$(date '+%d.%m.%Y %H:%M:%S')
send_deploy_notification() {
local status="$1" # success veya failure
local details="$2"
local header_emoji status_text color
if [[ "$status" == "success" ]]; then
header_emoji=":white_check_mark:"
status_text="BASARILI"
color="#36a64f"
else
header_emoji=":x:"
status_text="BASARISIZ"
color="#ff0000"
fi
cat <<EOF | curl -s -X POST -H 'Content-type: application/json' -d @- "$SLACK_WEBHOOK_URL"
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "${header_emoji} Deploy ${status_text}: ${APP_NAME}"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Uygulama:*n${APP_NAME}"
},
{
"type": "mrkdwn",
"text": "*Versiyon:*n${VERSION}"
},
{
"type": "mrkdwn",
"text": "*Ortam:*n${DEPLOY_ENV}"
},
{
"type": "mrkdwn",
"text": "*Yapan:*n${DEPLOY_USER}"
},
{
"type": "mrkdwn",
"text": "*Zaman:*n${DEPLOY_TIME}"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Detaylar:*n```${details}```"
}
},
{
"type": "divider"
}
]
}
EOF
}
# Kullanim
send_deploy_notification "success" "Docker image build edildi ve Kubernetes'e deploy edildi."
Python ile Gelişmiş Webhook Entegrasyonu
Daha karmaşık senaryolar için Python çok daha esneklik sunuyor. Özellikle hata yönetimi ve retry mekanizması için:
#!/usr/bin/env python3
# slack_notifier.py
import json
import os
import time
import urllib.request
import urllib.error
from datetime import datetime
from typing import Optional
class SlackNotifier:
def __init__(self, webhook_url: Optional[str] = None):
self.webhook_url = webhook_url or os.environ.get("SLACK_WEBHOOK_URL")
if not self.webhook_url:
raise ValueError("Slack webhook URL tanimli degil!")
self.max_retries = 3
self.retry_delay = 5
def send(self, message: str, emoji: str = ":robot_face:",
username: str = "ServerBot") -> bool:
payload = {
"text": message,
"username": username,
"icon_emoji": emoji
}
return self._post(payload)
def send_alert(self, title: str, message: str, severity: str = "warning",
fields: Optional[dict] = None) -> bool:
color_map = {
"info": "#36a64f",
"warning": "#ffaa00",
"critical": "#ff0000",
"success": "#36a64f"
}
attachment = {
"color": color_map.get(severity, "#cccccc"),
"title": title,
"text": message,
"fields": [],
"footer": f"Alert System | {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}",
"ts": int(time.time())
}
if fields:
for key, value in fields.items():
attachment["fields"].append({
"title": key,
"value": str(value),
"short": True
})
payload = {"attachments": [attachment]}
return self._post(payload)
def _post(self, payload: dict) -> bool:
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
self.webhook_url,
data=data,
headers={"Content-Type": "application/json"}
)
for attempt in range(1, self.max_retries + 1):
try:
with urllib.request.urlopen(req, timeout=10) as response:
if response.status == 200:
return True
except urllib.error.HTTPError as e:
print(f"HTTP Hata ({attempt}/{self.max_retries}): {e.code} - {e.reason}")
except urllib.error.URLError as e:
print(f"URL Hata ({attempt}/{self.max_retries}): {e.reason}")
except Exception as e:
print(f"Beklenmeyen hata ({attempt}/{self.max_retries}): {e}")
if attempt < self.max_retries:
time.sleep(self.retry_delay * attempt)
return False
# Kullanim ornegi
if __name__ == "__main__":
notifier = SlackNotifier()
# Basit mesaj
notifier.send(":wave: Python notifier baslatildi!")
# Alert mesaji
notifier.send_alert(
title="Yuksek CPU Kullanimi",
message="web-server-01 sunucusunda CPU kullanimi kritik seviyeye ulasti.",
severity="critical",
fields={
"Sunucu": "web-server-01",
"CPU Kullanimi": "%94",
"Surec": "nginx worker",
"PID": "12847"
}
)
Webhook URL’sini Güvenli Saklama
Webhook URL’sini script içine yazmak büyük bir güvenlik açığıdır. Doğru yöntemler şunlardır:
Environment Variable ile:
# /etc/environment dosyasina ekleyin (sistem geneli)
echo 'SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00000/B00000/XXXXX"' >> /etc/environment
# Ya da cron icin /etc/cron.d/ altindaki dosyaya:
# SLACK_WEBHOOK_URL=https://hooks.slack.com/...
# 0 * * * * root /usr/local/bin/disk_monitor.sh
# Script icinde kullanim:
WEBHOOK="${SLACK_WEBHOOK_URL:?Slack webhook URL tanimli degil!}"
Ayrı Konfigürasyon Dosyası ile:
# /etc/slack-notify.conf (sadece root okuyabilsin)
# chmod 600 /etc/slack-notify.conf
# chown root:root /etc/slack-notify.conf
cat > /etc/slack-notify.conf << 'EOF'
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00000/B00000/XXXXX"
SLACK_DEFAULT_CHANNEL="#alerts"
SLACK_USERNAME="ServerBot"
EOF
chmod 600 /etc/slack-notify.conf
# Script icinde kullanim:
source /etc/slack-notify.conf
Systemd Service ile:
# /etc/systemd/system/myapp.service dosyasina
[Service]
EnvironmentFile=/etc/myapp/secrets
ExecStart=/usr/local/bin/myapp
Logrotate Post-Action Bildirimi
Log rotasyonu tamamlandığında bildirim göndermek için:
# /etc/logrotate.d/nginx dosyasina eklenecek
/var/log/nginx/*.log {
daily
rotate 14
compress
postrotate
SLACK_WEBHOOK_URL=$(cat /etc/slack-notify.conf | grep SLACK_WEBHOOK | cut -d'"' -f2)
LOG_SIZE=$(du -sh /var/log/nginx/ | cut -f1)
curl -s -X POST -H 'Content-type: application/json'
--data "{"text":":arrows_counterclockwise: Nginx log rotasyonu tamamlandi. Toplam log boyutu: ${LOG_SIZE}"}"
"$SLACK_WEBHOOK_URL" > /dev/null 2>&1
endscript
}
Webhook Hata Ayıklama ve Sorun Giderme
Bir şeyler yanlış gittiğinde nereye bakmalısınız:
HTTP 400 – Bad Request: JSON formatınız hatalıdır. Payload’ı validate edin:
# JSON payload'i dogrula
echo '{"text": "test"}' | python3 -m json.tool
# Verbose curl ile detayli hata gorme
curl -v -X POST -H 'Content-type: application/json'
--data '{"text":"test"}'
"$SLACK_WEBHOOK_URL" 2>&1
HTTP 403 – Forbidden: Webhook URL geçersiz veya iptal edilmiştir. Slack admin panelinden yeni webhook oluşturun.
HTTP 429 – Too Many Requests: Rate limit’e takıldınız. Slack Incoming Webhooks için saniyede 1 mesaj sınırı var. Script’inize bekleme ekleyin:
# Rate limiting icin mesajlar arasina bekleme ekle
send_bulk_notifications() {
local messages=("$@")
for msg in "${messages[@]}"; do
send_slack_message "$msg"
sleep 1 # Rate limit: saniyede 1 mesaj
done
}
“no_service” hatası: Webhook URL’nizin üçüncü bölümündeki token yanlış veya eksik.
SSL sertifika hatası: Eski sistemlerde ca-certificates paketi güncel olmayabilir:
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install ca-certificates
# CentOS/RHEL
sudo yum update ca-certificates
# curl ile SSL dogrulamayi gecici devre disi birakmak (SADECE test icin!)
curl -k -X POST ...
Monitoring Entegrasyonu: Cronjob ile Periyodik Kontroller
Tüm öğrendiklerimizi birleştiren kapsamlı bir sistem health check scripti:
#!/bin/bash
# /usr/local/bin/system_health_check.sh
# Her 5 dakikada bir calistir: */5 * * * * root /usr/local/bin/system_health_check.sh
source /etc/slack-notify.conf
HOSTNAME=$(hostname -f)
ALERTS=()
ALERT_SENT=false
# CPU kontrolu
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1 | cut -d',' -f1)
CPU_INT=${CPU_USAGE%.*}
if [[ "$CPU_INT" -gt 90 ]]; then
ALERTS+=(":fire: CPU kullanimi: %${CPU_INT}")
fi
# RAM kontrolu
RAM_USAGE=$(free | awk '/Mem/{printf("%.0f", $3/$2*100)}')
if [[ "$RAM_USAGE" -gt 85 ]]; then
ALERTS+=(":warning: RAM kullanimi: %${RAM_USAGE}")
fi
# Load average kontrolu
LOAD_AVG=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
CPU_COUNT=$(nproc)
LOAD_INT=${LOAD_AVG%.*}
if [[ "$LOAD_INT" -gt "$CPU_COUNT" ]]; then
ALERTS+=(":chart_with_upwards_trend: Yuksek load average: ${LOAD_AVG} (${CPU_COUNT} CPU)")
fi
# Kritik servis kontrolu
SERVICES=("nginx" "mysql" "redis")
for service in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$service" 2>/dev/null; then
ALERTS+=(":rotating_light: ${service} servisi calismiyor!")
fi
done
# Alert varsa gonder
if [[ "${#ALERTS[@]}" -gt 0 ]]; then
ALERT_TEXT="*:hospital: ${HOSTNAME} - Sistem Uyarilari*n"
for alert in "${ALERTS[@]}"; do
ALERT_TEXT+="• ${alert}n"
done
ALERT_TEXT+="n_$(date '+%d.%m.%Y %H:%M:%S')_"
curl -s -X POST -H 'Content-type: application/json'
--data "{"text":"${ALERT_TEXT}"}"
"$SLACK_WEBHOOK_URL" > /dev/null
ALERT_SENT=true
fi
exit 0
Pratik İpuçları ve En İyi Uygulamalar
Webhook entegrasyonlarınızda dikkat etmeniz gereken birkaç önemli nokta var.
Kanal stratejisi belirleyin: Her şeyi tek bir kanala göndermek yerine, önem seviyesine göre farklı webhook’lar oluşturun. #alerts-critical sadece acil durumlar için, #alerts-info ise rutin bildirimler için kullanılabilir.
Mesaj deduplication uygulayın: Aynı hatayı her dakika göndermek yerine, gönderilen uyarıları lock dosyasıyla takip edin:
LOCK_FILE="/tmp/slack_disk_alert_$(echo $mount_point | tr '/' '_').lock"
# Lock dosyasi son 4 saatten eskiyse alert gonder
if [[ ! -f "$LOCK_FILE" ]] || [[ $(find "$LOCK_FILE" -mmin +240 2>/dev/null) ]]; then
send_alert "$mount" "$usage" "warning"
touch "$LOCK_FILE"
fi
Tüm Slack mesajlarını logla: Bir şeyler ters gittiğinde geriye dönüp bakabilmek için:
LOG_FILE="/var/log/slack-notifications.log"
log_and_send() {
local message="$1"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $message" >> "$LOG_FILE"
send_slack_message "$message"
}
Timeout ekleyin: Ağ sorunlarında scriptlerinizin takılıp kalmaması için curl komutlarınıza her zaman --max-time ve --connect-timeout parametresi ekleyin:
curl --max-time 10 --connect-timeout 5
-s -X POST -H 'Content-type: application/json'
--data "$payload" "$SLACK_WEBHOOK_URL"
Sonuç
Slack webhook entegrasyonu, sysadmin araç kutunuzun vazgeçilmez bir parçası olmalı. Birkaç satır bash veya Python kodu ile monitoring sistemleriniz, cron job’larınız ve deployment pipeline’larınız artık sessizce değil, sesli çalışmaya başlıyor. Bir disk dolduğunda, bir servis çöktüğünde veya bir deploy tamamlandığında anında haberdar olmak; sorunları kullanıcılar fark etmeden çözmenizi sağlıyor.
Başlamak için karmaşık bir kuruluma ihtiyacınız yok: Slack’te bir app oluşturun, webhook URL’nizi alın ve ilk curl komutunuzu çalıştırın. Ardından bu yazıdaki örnekleri kendi altyapınıza göre uyarlayın. Disk monitor’den başlayın, çalıştığını gördükten sonra servisleri, load average’ı ve deployment süreçlerini ekleyin. Zamanla tüm kritik olaylarınızın Slack’te toplandığını ve ekibinizin çok daha hızlı tepki verdiğini göreceksiniz.
Son olarak şunu unutmayın: Webhook URL’nizi güvende tutun. Bu URL sızdığında, yapılandırma yönetim sisteminizden yenisini hızlıca oluşturup dağıtabilmeniz için webhook URL’lerini merkezi bir secrets yönetim aracında (HashiCorp Vault, AWS Secrets Manager veya en azından şifrelenmiş bir dosyada) tutma alışkanlığı edinin.
