| Server IP : 119.195.102.159 / Your IP : 216.73.217.134 Web Server : nginx/1.18.0 System : Linux picell 5.15.0-181-generic #191-Ubuntu SMP Fri May 22 19:09:02 UTC 2026 x86_64 User : altablue ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/altablue/ |
Upload File : |
#!/bin/bash
# ============================================================
# π PHP-FPM ν¬μ€μ²΄ν¬ + 보μ ν΅ν© μμΉλ
# μλ² λ°°ν¬ κ²½λ‘: /home/altablue/watch_fpm.sh
#
# κΈ°μ‘΄ κΈ°λ₯: μΉμ¬μ΄νΈ μλ΅ νμΈ β PHP-FPM μ¬μμ
# μΆκ° κΈ°λ₯: μ°μ μ€ν¨ μμ€μ»¬λ μ΄μ
, μλ΅ μκ° λͺ¨λν°λ§,
# 보μ μμ€ν
μν νμΈ, μΌμΌ μμ½ λ³΄κ³
#
# ν¬λ‘ : * * * * * /home/altablue/watch_fpm.sh
# ============================================================
# ββ μ€μ λ‘λ βββββββββββββββββββββββββββββββββββββ
CONFIG_FILE="/etc/security-watchdog/config"
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
else
# ν΄λ°± μ€μ
HEALTH_CHECK_URL="https://www.picell.biz/about-us/"
HEALTH_CHECK_TIMEOUT=5
FPM_SERVICE="php8.3-fpm"
LOG_DIR="/home/altablue/logs"
fi
# ββ κ²½λ‘ μ€μ βββββββββββββββββββββββββββββββββββββ
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
NOTIFY="$SCRIPT_DIR/telegram_notify.sh"
LOGFILE="${LOG_DIR:-/home/altablue/logs}/fpm_watchdog.log"
FAIL_COUNT_FILE="/tmp/.fpm_watchdog_fail_count"
SLOW_LOG="${LOG_DIR:-/home/altablue/logs}/slow_response.log"
DAILY_STATS_FILE="/tmp/.fpm_daily_stats"
# ββ λλ¦° μλ΅ κ΄λ ¨ μν νμΌ βββββββββββββββββββββ
SLOW_COUNT_FILE="/tmp/.fpm_slow_count" # μ°μ λλ¦° μλ΅ νμ
SLOW_ALERT_FILE="/tmp/.fpm_slow_alerted" # λ§μ§λ§ λλ¦° μλ΅ μλ¦Ό μκ°
SLOW_ATTACK_FILE="/tmp/.fpm_slow_attack" # μ¬λ‘μ° μ΄ν νμ§ μλ¦Ό μκ°
SLOW_THRESHOLD="${SLOW_RESPONSE_THRESHOLD:-5.0}" # λλ¦° μλ΅ κΈ°μ€(μ΄)
SLOW_RESTART_THRESHOLD="${SLOW_RESTART_THRESHOLD:-10.0}" # μλ μ¬μμ κΈ°μ€(μ΄)
SLOW_ALERT_COOLDOWN=1800 # λλ¦° μλ΅ μλ¦Ό μΏ¨λ€μ΄(30λΆ)
SLOW_ALERT_COUNT_TRIGGER=3 # Nμ°μ λ
Έλ¦΄ λλ§ μλ¦Ό
ATTACK_CONN_THRESHOLD="${SLOW_ATTACK_CONN_THRESHOLD:-300}" # μ¬λ‘μ° μ΄ν ESTABLISHED μκ³κ°
mkdir -p "$(dirname "$LOGFILE")" 2>/dev/null
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
HOUR=$(date "+%H")
MINUTE=$(date "+%M")
# ββ μΉμ¬μ΄νΈ μλ΅ νμΈ (μλ΅ μκ° ν¬ν¨) ββββββββββ
RESPONSE=$(curl -s -o /dev/null \
-w "%{http_code}|%{time_total}|%{time_connect}|%{time_starttransfer}" \
--max-time "${HEALTH_CHECK_TIMEOUT:-5}" \
"${HEALTH_CHECK_URL}" 2>/dev/null)
STATUS=$(echo "$RESPONSE" | cut -d'|' -f1)
TIME_TOTAL=$(echo "$RESPONSE" | cut -d'|' -f2)
TIME_CONNECT=$(echo "$RESPONSE" | cut -d'|' -f3)
TIME_TTFB=$(echo "$RESPONSE" | cut -d'|' -f4)
# ββ μ°μ μ€ν¨ μΉ΄μ΄νΈ κ΄λ¦¬ βββββββββββββββββββββββββ
FAIL_COUNT=0
if [ -f "$FAIL_COUNT_FILE" ]; then
FAIL_COUNT=$(cat "$FAIL_COUNT_FILE" 2>/dev/null || echo 0)
fi
# ββ μΌμΌ ν΅κ³ κ΄λ¦¬ ββββββββββββββββββββββββββββββββ
TODAY=$(date "+%Y-%m-%d")
if [ -f "$DAILY_STATS_FILE" ]; then
STATS_DATE=$(head -1 "$DAILY_STATS_FILE" 2>/dev/null || echo "")
if [ "$STATS_DATE" != "$TODAY" ]; then
# μλ‘μ΄ λ β μ΄μ ν΅κ³ 리μ
echo "$TODAY" > "$DAILY_STATS_FILE"
echo "0" >> "$DAILY_STATS_FILE" # μ΄ μ²΄ν¬ μ
echo "0" >> "$DAILY_STATS_FILE" # μ€ν¨ μ
echo "0" >> "$DAILY_STATS_FILE" # μ¬μμ μ
echo "0" >> "$DAILY_STATS_FILE" # λλ¦° μλ΅ μ
fi
else
echo "$TODAY" > "$DAILY_STATS_FILE"
echo "0" >> "$DAILY_STATS_FILE"
echo "0" >> "$DAILY_STATS_FILE"
echo "0" >> "$DAILY_STATS_FILE"
echo "0" >> "$DAILY_STATS_FILE"
fi
# ν΅κ³ μ½κΈ°
STATS_CHECKS=$(sed -n '2p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
STATS_FAILS=$(sed -n '3p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
STATS_RESTARTS=$(sed -n '4p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
STATS_SLOW=$(sed -n '5p' "$DAILY_STATS_FILE" 2>/dev/null || echo 0)
# μ΄ μ²΄ν¬ μ μ¦κ°
STATS_CHECKS=$((STATS_CHECKS + 1))
# ββ μλ΅ λΆμ βββββββββββββββββββββββββββββββββββββ
if [ "$STATUS" != "200" ]; then
# ββββββ μ€ν¨ μ²λ¦¬ ββββββ
FAIL_COUNT=$((FAIL_COUNT + 1))
echo "$FAIL_COUNT" > "$FAIL_COUNT_FILE"
STATS_FAILS=$((STATS_FAILS + 1))
echo "[$TIMESTAMP] β μλ΅ μ΄μ (Status: $STATUS, μ°μμ€ν¨: $FAIL_COUNT)" >> "$LOGFILE"
# PHP-FPM μ¬μμ
systemctl restart "${FPM_SERVICE}" 2>/dev/null
STATS_RESTARTS=$((STATS_RESTARTS + 1))
echo "[$TIMESTAMP] π ${FPM_SERVICE} μ¬μμ μλ£" >> "$LOGFILE"
# μμ€μ»¬λ μ΄μ
λ‘μ§
if [ "$FAIL_COUNT" -ge 5 ]; then
# 5ν μ°μ μ€ν¨ β CRITICAL
"$NOTIFY" "CRITICAL" "π¨ <b>PHP-FPM μ°μ μ€ν¨ (${FAIL_COUNT}ν)</b>
π URL: ${HEALTH_CHECK_URL}
π Status: ${STATUS}
π ${FPM_SERVICE} μ¬μμ ${FAIL_COUNT}ν μλ
β οΈ μλ² μνλ₯Ό μ¦μ νμΈν΄μ£ΌμΈμ!
κ°λ₯ν μμΈ:
β’ μλ² κ³ΌλΆν
β’ λμ€ν¬ μ©λ λΆμ‘±
β’ MySQL λ€μ΄
⒠DDoS 곡격"
# 10ν μ΄μμ΄λ©΄ nginxλ μ¬μμ μλ
if [ "$FAIL_COUNT" -ge 10 ]; then
systemctl restart nginx 2>/dev/null
echo "[$TIMESTAMP] π nginx μ¬μμ μλ (μ°μ μ€ν¨ ${FAIL_COUNT}ν)" >> "$LOGFILE"
fi
elif [ "$FAIL_COUNT" -ge 3 ]; then
# 3ν μ°μ μ€ν¨ β WARNING
"$NOTIFY" "WARNING" "β οΈ <b>PHP-FPM λ°λ³΅ μ€ν¨ (${FAIL_COUNT}ν μ°μ)</b>
π URL: ${HEALTH_CHECK_URL}
π Status: ${STATUS}
π ${FPM_SERVICE} μ¬μμλ¨"
else
# 1~2ν β μΌλ° κ²½κ³
"$NOTIFY" "WARNING" "β οΈ PHP-FPM μ¬μμλ¨
π μλ΅: ${STATUS}
π μ°μ μ€ν¨: ${FAIL_COUNT}ν"
fi
else
# ββββββ μ±κ³΅ μ²λ¦¬ ββββββ
# μ€ν¨ μΉ΄μ΄νΈ 리μ
(μ΄μ μ μ€ν¨νλ€λ©΄ 볡ꡬ μλ¦Ό)
if [ "$FAIL_COUNT" -gt 0 ]; then
echo "[$TIMESTAMP] β
λ³΅κ΅¬λ¨ (μ΄μ μ°μμ€ν¨: ${FAIL_COUNT}ν)" >> "$LOGFILE"
"$NOTIFY" "INFO" "β
<b>μλΉμ€ 볡ꡬ νμΈ</b>
π ${HEALTH_CHECK_URL}
π Status: 200 OK
β±οΈ μλ΅ μκ°: ${TIME_TOTAL}s
π μ΄μ μ°μ μ€ν¨: ${FAIL_COUNT}νμμ 볡ꡬ"
echo "0" > "$FAIL_COUNT_FILE"
fi
# ββ λλ¦° μλ΅ κ°μ§ βββββββββββββββββββββββββββββββββ
if [ -n "$TIME_TOTAL" ] && (( $(echo "$TIME_TOTAL > $SLOW_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
STATS_SLOW=$((STATS_SLOW + 1))
echo "[$TIMESTAMP] π λλ¦° μλ΅: ${TIME_TOTAL}s (TTFB: ${TIME_TTFB}s)" >> "$SLOW_LOG"
# μ°μ λλ¦° μλ΅ νμ μ
λ°μ΄νΈ
SLOW_COUNT=0
[ -f "$SLOW_COUNT_FILE" ] && SLOW_COUNT=$(cat "$SLOW_COUNT_FILE" 2>/dev/null || echo 0)
SLOW_COUNT=$((SLOW_COUNT + 1))
echo "$SLOW_COUNT" > "$SLOW_COUNT_FILE"
echo "[$TIMESTAMP] π λλ¦° μλ΅ (${TIME_TOTAL}s, TTFB: ${TIME_TTFB}s, μ°μ: ${SLOW_COUNT}ν)" >> "$LOGFILE"
# ββ ESTABLISHED μ°κ²° μ νμΈ (μ¬λ‘μ° HTTP μ΄ν νλ¨) ββββ
CONN_COUNT=$(ss -s 2>/dev/null | grep -oP 'estab \K[0-9]+' | head -1 || echo 0)
IS_ATTACK=0
if (( CONN_COUNT > ATTACK_CONN_THRESHOLD )) && \
(( $(echo "$TIME_TOTAL > $SLOW_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
IS_ATTACK=1
fi
# ββ μλ μ¬μμ: 10μ΄ μ΄μ OR μ¬λ‘μ° μ΄ν νμ§ ββββ
SHOULD_RESTART=0
RESTART_REASON=""
if (( $(echo "$TIME_TOTAL > $SLOW_RESTART_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
SHOULD_RESTART=1
RESTART_REASON="μλ΅μκ° ${TIME_TOTAL}s μ΄κ³Ό (μκ³: ${SLOW_RESTART_THRESHOLD}s)"
elif [ "$IS_ATTACK" -eq 1 ]; then
SHOULD_RESTART=1
RESTART_REASON="μ¬λ‘μ° HTTP μ΄ν νμ§ (ESTABLISHED: ${CONN_COUNT}, μλ΅: ${TIME_TOTAL}s)"
fi
if [ "$SHOULD_RESTART" -eq 1 ]; then
systemctl restart "${FPM_SERVICE}" 2>/dev/null
STATS_RESTARTS=$((STATS_RESTARTS + 1))
echo "[$TIMESTAMP] π ${FPM_SERVICE} μ¬μμ: $RESTART_REASON" >> "$LOGFILE"
# μ¬λ‘μ° μ΄ν μλ¦Ό (30λΆ μΏ¨λ€μ΄)
NOW=$(date +%s)
LAST_ATTACK_ALERT=0
[ -f "$SLOW_ATTACK_FILE" ] && LAST_ATTACK_ALERT=$(cat "$SLOW_ATTACK_FILE" 2>/dev/null || echo 0)
if (( NOW - LAST_ATTACK_ALERT > SLOW_ALERT_COOLDOWN )); then
"$NOTIFY" "CRITICAL" "π¨ <b>PHP-FPM μλ μ¬μμ</b>
β‘ μμΈ: $RESTART_REASON
π νμ± μ°κ²°: ${CONN_COUNT}κ°
β±οΈ μλ΅μκ°: ${TIME_TOTAL}s (TTFB: ${TIME_TTFB}s)
π ${FPM_SERVICE} μ¬μμ μλ£
β οΈ λ€μ μλ¦Ό: 30λΆ ν"
date +%s > "$SLOW_ATTACK_FILE"
fi
echo "0" > "$SLOW_COUNT_FILE"
fi
# ββ μΌλ° λλ¦° μλ΅ μλ¦Ό (μΏ¨λ€μ΄ + Nν μ°μ 쑰건) ββββ
# μΏ¨λ€μ΄ λ΄μ΄λ©΄ μλ¦Ό μ 보λ β μλ¦Ό νΌλ‘λ ν΄μ
NOW=$(date +%s)
LAST_SLOW_ALERT=0
[ -f "$SLOW_ALERT_FILE" ] && LAST_SLOW_ALERT=$(cat "$SLOW_ALERT_FILE" 2>/dev/null || echo 0)
COOLDOWN_ELAPSED=$(( NOW - LAST_SLOW_ALERT ))
if [ "$SHOULD_RESTART" -eq 0 ] && \
[ "$SLOW_COUNT" -ge "$SLOW_ALERT_COUNT_TRIGGER" ] && \
(( COOLDOWN_ELAPSED > SLOW_ALERT_COOLDOWN )); then
"$NOTIFY" "WARNING" "π <b>μ§μμ λλ¦° μλ΅</b>
π ${HEALTH_CHECK_URL}
β±οΈ μλ΅μκ°: ${TIME_TOTAL}s
π TTFB: ${TIME_TTFB}s
π ESTABLISHED: ${CONN_COUNT}κ°
π μ°μ ${SLOW_COUNT}ν λ
Έλ¦΄
β οΈ λ€μ μλ¦Ό: 30λΆ ν"
date +%s > "$SLOW_ALERT_FILE"
fi
else
# μλ΅ μ μ β λλ¦° μλ΅ μΉ΄μ΄ν° 리μ
if [ -f "$SLOW_COUNT_FILE" ]; then
PREV_SLOW=$(cat "$SLOW_COUNT_FILE" 2>/dev/null || echo 0)
if [ "$PREV_SLOW" -gt 0 ]; then
echo "[$TIMESTAMP] β
λλ¦° μλ΅ ν΄μ (μ°μ ${PREV_SLOW}ν)"
fi
echo "0" > "$SLOW_COUNT_FILE"
fi
echo "[$TIMESTAMP] β
μ μ (Status: $STATUS, Time: ${TIME_TOTAL}s)" >> "$LOGFILE"
fi
echo "0" > "$FAIL_COUNT_FILE"
fi
# ββ μΌμΌ ν΅κ³ μ μ₯ ββββββββββββββββββββββββββββββββ
cat > "$DAILY_STATS_FILE" << EOF
$TODAY
$STATS_CHECKS
$STATS_FAILS
$STATS_RESTARTS
$STATS_SLOW
EOF
# ββ μΌμΌ μμ½ λ³΄κ³ (λ§€μΌ 23:59μ μ€ν) ββββββββββββ
if [ "$HOUR" = "23" ] && [ "$MINUTE" = "59" ]; then
UPTIME_PERCENT=0
if [ "$STATS_CHECKS" -gt 0 ]; then
UPTIME_PERCENT=$(echo "scale=2; (($STATS_CHECKS - $STATS_FAILS) * 100) / $STATS_CHECKS" | bc 2>/dev/null || echo "N/A")
fi
# 보μ μμ€ν
μν νμΈ
FIM_STATUS="β μ€μ§λ¨"
if systemctl is-active --quiet file-integrity-monitor 2>/dev/null; then
FIM_STATUS="β
μ€ν μ€"
fi
# μ€λμ 보μ μ΄λ²€νΈ μ
SECURITY_EVENTS=0
if [ -f "${LOG_DIR}/alert_history.log" ]; then
SECURITY_EVENTS=$(grep -c "$(date +%Y-%m-%d)" "${LOG_DIR}/alert_history.log" 2>/dev/null || echo 0)
fi
# 격리λ νμΌ μ
QUARANTINE_COUNT=0
if [ -d "$QUARANTINE_DIR" ]; then
QUARANTINE_COUNT=$(find "$QUARANTINE_DIR" -maxdepth 1 -type f -newer "$DAILY_STATS_FILE" 2>/dev/null | wc -l)
fi
"$NOTIFY" "DAILY" "π <b>μΌμΌ μλ² λ³΄μ λ³΄κ³ μ</b>
ββββββββββββββββββββ
π <b>μλΉμ€ μν:</b>
β’ κ°λλ₯ : ${UPTIME_PERCENT}%
β’ μ΄ μ²΄ν¬: ${STATS_CHECKS}ν
β’ μ€ν¨: ${STATS_FAILS}ν
β’ FPM μ¬μμ: ${STATS_RESTARTS}ν
β’ λλ¦° μλ΅: ${STATS_SLOW}ν
π‘οΈ <b>보μ μν:</b>
β’ νμΌ κ°μ: ${FIM_STATUS}
⒠보μ μ΄λ²€νΈ: ${SECURITY_EVENTS}건
⒠격리 νμΌ: ${QUARANTINE_COUNT}κ°
π
λ μ§: ${TODAY}"
fi
# ββ λ‘κ·Έ ν¬κΈ° κ΄λ¦¬ (50MB μ΄κ³Ό μ νΈλ¦Ό) ββββββββββββ
if [ -f "$LOGFILE" ]; then
LOG_SIZE=$(stat -c%s "$LOGFILE" 2>/dev/null || echo 0)
if [ "$LOG_SIZE" -gt 52428800 ]; then
tail -n 10000 "$LOGFILE" > "${LOGFILE}.tmp"
mv "${LOGFILE}.tmp" "$LOGFILE"
fi
fi