|
| 1 | +#!/bin/bash |
| 2 | +# ═══════════════════════════════════════════════════════════════════════════════ |
| 3 | +# NitroWebExpress™ — Frontend Diagnosis |
| 4 | +# Finds why webapps return 404 after post-clone.sh / start-all.sh. |
| 5 | +# |
| 6 | +# Usage: bash scripts/frontend-diagnosis.sh [tomcat_home] |
| 7 | +# ═══════════════════════════════════════════════════════════════════════════════ |
| 8 | +set -uo pipefail |
| 9 | + |
| 10 | +PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" |
| 11 | +TOMCAT_HOME="${1:-${CATALINA_HOME:-/home/mearvk/tomcat}}" |
| 12 | + |
| 13 | +PASS=0; FAIL=0; WARN=0 |
| 14 | +pass() { PASS=$((PASS+1)); echo " [PASS] $1"; } |
| 15 | +fail() { FAIL=$((FAIL+1)); echo " [FAIL] $1"; } |
| 16 | +warn() { WARN=$((WARN+1)); echo " [WARN] $1"; } |
| 17 | +info() { echo " [INFO] $1"; } |
| 18 | + |
| 19 | +# context|deploy_script|backend_class|port|db |
| 20 | +MODULES=( |
| 21 | + "california-fbi|modules/fbi/servlets/deploy-local.sh|source.CaliforniaFBIServer|49210|nwe_california_fbi" |
| 22 | + "california-cia|modules/cia/servlets/deploy-local.sh|source.CaliforniaCIAServer|49211|nwe_california_cia" |
| 23 | + "california-nsa|modules/nsa/servlets/deploy-local.sh|source.CaliforniaNSAServer|49212|nwe_california_nsa" |
| 24 | + "california-duke|modules/duke/servlets/deploy-local.sh|source.DukeUniversityServer|49213|nwe_duke" |
| 25 | + "library|modules/library/servlets/deploy-local.sh|source.StanfordLibraryServer|49214|nwe_library" |
| 26 | + "ae6e66|modules/AE6E66/servlets/deploy-local.sh|source.AE6E66Main|0|nwe_ae6e66" |
| 27 | + "futures|modules/red/Futures/servlets/deploy-local.sh|red.Futures.source.ai.server.DemocraticAIServer|5000|nwe_futures" |
| 28 | + "gdgh|modules/Green.Durham.Grass.and.Herb/servlets/deploy-local.sh|listeners.BaseListener|20000|nwe_gdgh" |
| 29 | + "gray-registry|modules/gray/servlets/deploy-local.sh|modules.gray.source.GrayPortRegistryServer|9999|nwe_gray_registry" |
| 30 | + "gray85-registry|modules/gray.a85/servlets/deploy-local.sh|modules.gray.a85.source.Gray85PortRegistryServer|10085|nwe_gray85_registry" |
| 31 | + "blackbelt|modules/black-belt/servlets/deploy-local.sh||0|" |
| 32 | + "languages|modules/languages/servlets/deploy-local.sh||0|" |
| 33 | + "brarner.m.alete|modules/black/presidential/Brarner.M.Alete/install/deploy-local.sh||49152|BrarnerScience" |
| 34 | +) |
| 35 | + |
| 36 | +echo "" |
| 37 | +echo "╔═══════════════════════════════════════════════════════════════════════════╗" |
| 38 | +echo "║ NitroWebExpress™ — Frontend Diagnosis ║" |
| 39 | +echo "║ Tomcat: $TOMCAT_HOME" |
| 40 | +echo "║ Project: $PROJECT_ROOT" |
| 41 | +echo "╚═══════════════════════════════════════════════════════════════════════════╝" |
| 42 | + |
| 43 | +# ───────────────────────────────────────────────────────────────────────────── |
| 44 | +echo "" |
| 45 | +echo "── 1. Tomcat Process & HTTP ──" |
| 46 | +echo "" |
| 47 | + |
| 48 | +TOMCAT_PID=$(pgrep -f "catalina" 2>/dev/null | head -1) |
| 49 | +if [ -n "$TOMCAT_PID" ]; then |
| 50 | + pass "Tomcat running (PID $TOMCAT_PID)" |
| 51 | +else |
| 52 | + fail "Tomcat NOT running" |
| 53 | + info "Fix: $TOMCAT_HOME/bin/startup.sh" |
| 54 | +fi |
| 55 | + |
| 56 | +HTTP_ROOT=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://localhost:8080/ 2>/dev/null || echo "000") |
| 57 | +if [[ "$HTTP_ROOT" =~ ^(200|302|401|403)$ ]]; then |
| 58 | + pass "Tomcat root responds HTTP $HTTP_ROOT" |
| 59 | +else |
| 60 | + fail "Tomcat root: HTTP $HTTP_ROOT" |
| 61 | +fi |
| 62 | + |
| 63 | +# ───────────────────────────────────────────────────────────────────────────── |
| 64 | +echo "" |
| 65 | +echo "── 2. server.xml autoDeploy ──" |
| 66 | +echo "" |
| 67 | + |
| 68 | +SERVER_XML="$TOMCAT_HOME/conf/server.xml" |
| 69 | +if [ -f "$SERVER_XML" ]; then |
| 70 | + if grep -q 'autoDeploy="false"' "$SERVER_XML"; then |
| 71 | + fail "autoDeploy=false in server.xml — Tomcat won't load new webapps" |
| 72 | + info "Fix: set autoDeploy=\"true\" in <Host> element" |
| 73 | + else |
| 74 | + pass "autoDeploy enabled (true or default)" |
| 75 | + fi |
| 76 | + APP_BASE=$(grep -oP 'appBase="\K[^"]+' "$SERVER_XML" | head -1) |
| 77 | + APP_BASE="${APP_BASE:-webapps}" |
| 78 | + if [[ "$APP_BASE" == /* ]]; then |
| 79 | + WEBAPPS_DIR="$APP_BASE" |
| 80 | + else |
| 81 | + WEBAPPS_DIR="$TOMCAT_HOME/$APP_BASE" |
| 82 | + fi |
| 83 | + if [ -d "$WEBAPPS_DIR" ]; then |
| 84 | + pass "appBase exists: $WEBAPPS_DIR" |
| 85 | + else |
| 86 | + fail "appBase MISSING: $WEBAPPS_DIR" |
| 87 | + fi |
| 88 | +else |
| 89 | + fail "server.xml not found: $SERVER_XML" |
| 90 | + WEBAPPS_DIR="$TOMCAT_HOME/webapps" |
| 91 | +fi |
| 92 | + |
| 93 | +# ───────────────────────────────────────────────────────────────────────────── |
| 94 | +echo "" |
| 95 | +echo "── 3. Context XML Pointers ──" |
| 96 | +echo "" |
| 97 | + |
| 98 | +CTX_DIR="$TOMCAT_HOME/conf/Catalina/localhost" |
| 99 | +if [ -d "$CTX_DIR" ] && ls "$CTX_DIR"/*.xml &>/dev/null; then |
| 100 | + for CTX_FILE in "$CTX_DIR"/*.xml; do |
| 101 | + CTX_NAME=$(basename "$CTX_FILE" .xml) |
| 102 | + DOC_BASE=$(grep -oP 'docBase="\K[^"]+' "$CTX_FILE" 2>/dev/null) |
| 103 | + if [ -n "$DOC_BASE" ]; then |
| 104 | + if [ -d "$DOC_BASE" ]; then |
| 105 | + pass "$CTX_NAME → $DOC_BASE (exists)" |
| 106 | + else |
| 107 | + fail "$CTX_NAME → $DOC_BASE (MISSING — 404 guaranteed)" |
| 108 | + info "Fix: remove $CTX_FILE or fix docBase path" |
| 109 | + fi |
| 110 | + fi |
| 111 | + done |
| 112 | +else |
| 113 | + info "No context XMLs in $CTX_DIR — Tomcat uses $WEBAPPS_DIR scanning" |
| 114 | +fi |
| 115 | + |
| 116 | +# ───────────────────────────────────────────────────────────────────────────── |
| 117 | +echo "" |
| 118 | +echo "── 4. Webapp Directory & web.xml ──" |
| 119 | +echo "" |
| 120 | + |
| 121 | +for MOD in "${MODULES[@]}"; do |
| 122 | + IFS='|' read -r CTX SCRIPT CLASS PORT DB <<< "$MOD" |
| 123 | + DIR="$WEBAPPS_DIR/$CTX" |
| 124 | + |
| 125 | + if [ ! -d "$DIR" ]; then |
| 126 | + fail "/$CTX — directory MISSING in $WEBAPPS_DIR" |
| 127 | + info " Deploy: bash $PROJECT_ROOT/$SCRIPT" |
| 128 | + continue |
| 129 | + fi |
| 130 | + |
| 131 | + FILES=$(find "$DIR" -type f 2>/dev/null | wc -l) |
| 132 | + if [ "$FILES" -lt 2 ]; then |
| 133 | + fail "/$CTX — directory exists but only $FILES file(s)" |
| 134 | + continue |
| 135 | + fi |
| 136 | + |
| 137 | + if [ -f "$DIR/WEB-INF/web.xml" ]; then |
| 138 | + pass "/$CTX — web.xml present ($FILES files)" |
| 139 | + else |
| 140 | + fail "/$CTX — NO WEB-INF/web.xml ($FILES files) — Tomcat ignores this" |
| 141 | + info " Tomcat requires web.xml to register the context" |
| 142 | + fi |
| 143 | +done |
| 144 | + |
| 145 | +# ───────────────────────────────────────────────────────────────────────────── |
| 146 | +echo "" |
| 147 | +echo "── 5. db.properties ──" |
| 148 | +echo "" |
| 149 | + |
| 150 | +for MOD in "${MODULES[@]}"; do |
| 151 | + IFS='|' read -r CTX SCRIPT CLASS PORT DB <<< "$MOD" |
| 152 | + [ -z "$DB" ] && continue |
| 153 | + DIR="$WEBAPPS_DIR/$CTX" |
| 154 | + [ ! -d "$DIR" ] && continue |
| 155 | + PROPS="$DIR/WEB-INF/db.properties" |
| 156 | + |
| 157 | + if [ -f "$PROPS" ] && grep -q "db.password=." "$PROPS" 2>/dev/null && ! grep -q "CHANGE_ME" "$PROPS" 2>/dev/null; then |
| 158 | + pass "/$CTX — db.properties OK" |
| 159 | + else |
| 160 | + fail "/$CTX — db.properties missing or placeholder" |
| 161 | + info " Fix: source scripts/deploy-functions.sh && nwe_ensure_db_properties '$DIR' '$DB' '$PROJECT_ROOT'" |
| 162 | + fi |
| 163 | +done |
| 164 | + |
| 165 | +# ───────────────────────────────────────────────────────────────────────────── |
| 166 | +echo "" |
| 167 | +echo "── 6. Backend .class Verification ──" |
| 168 | +echo "" |
| 169 | + |
| 170 | +OUT="$PROJECT_ROOT/out" |
| 171 | +if [ ! -d "$OUT" ]; then |
| 172 | + fail "out/ directory missing — nothing is compiled" |
| 173 | + info "Fix: bash scripts/compile-all-modules.sh" |
| 174 | +else |
| 175 | + for MOD in "${MODULES[@]}"; do |
| 176 | + IFS='|' read -r CTX SCRIPT CLASS PORT DB <<< "$MOD" |
| 177 | + [ -z "$CLASS" ] && continue |
| 178 | + CLASS_FILE="$OUT/$(echo "$CLASS" | tr '.' '/').class" |
| 179 | + if [ -f "$CLASS_FILE" ]; then |
| 180 | + if javap -p "$CLASS_FILE" 2>/dev/null | grep -q "public static.*void main"; then |
| 181 | + pass "$CLASS — compiled with main()" |
| 182 | + elif javap -p "$CLASS_FILE" 2>/dev/null | grep -q "public void run"; then |
| 183 | + pass "$CLASS — compiled with run() (Thread)" |
| 184 | + else |
| 185 | + warn "$CLASS — compiled but no main() or run() found" |
| 186 | + fi |
| 187 | + else |
| 188 | + fail "$CLASS — NOT COMPILED: $CLASS_FILE missing" |
| 189 | + info " Fix: bash scripts/compile-all-modules.sh" |
| 190 | + fi |
| 191 | + done |
| 192 | +fi |
| 193 | + |
| 194 | +# ───────────────────────────────────────────────────────────────────────────── |
| 195 | +echo "" |
| 196 | +echo "── 7. HTTP Endpoint Test ──" |
| 197 | +echo "" |
| 198 | + |
| 199 | +HTTP_OK=0; HTTP_FAIL=0 |
| 200 | + |
| 201 | +for MOD in "${MODULES[@]}"; do |
| 202 | + IFS='|' read -r CTX SCRIPT CLASS PORT DB <<< "$MOD" |
| 203 | + CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "http://localhost:8080/$CTX/" 2>/dev/null || echo "000") |
| 204 | + |
| 205 | + if [[ "$CODE" =~ ^(200|302)$ ]]; then |
| 206 | + pass "/$CTX → HTTP $CODE" |
| 207 | + HTTP_OK=$((HTTP_OK+1)) |
| 208 | + else |
| 209 | + fail "/$CTX → HTTP $CODE" |
| 210 | + HTTP_FAIL=$((HTTP_FAIL+1)) |
| 211 | + fi |
| 212 | +done |
| 213 | + |
| 214 | +# ───────────────────────────────────────────────────────────────────────────── |
| 215 | +echo "" |
| 216 | +echo "── 8. Auto-Fix (redeploy failing modules + restart Tomcat) ──" |
| 217 | +echo "" |
| 218 | + |
| 219 | +if [ "$HTTP_FAIL" -gt 0 ]; then |
| 220 | + echo " $HTTP_FAIL module(s) returning non-200. Attempting redeploy..." |
| 221 | + echo "" |
| 222 | + |
| 223 | + for MOD in "${MODULES[@]}"; do |
| 224 | + IFS='|' read -r CTX SCRIPT CLASS PORT DB <<< "$MOD" |
| 225 | + CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 "http://localhost:8080/$CTX/" 2>/dev/null || echo "000") |
| 226 | + [[ "$CODE" =~ ^(200|302)$ ]] && continue |
| 227 | + |
| 228 | + FULL="$PROJECT_ROOT/$SCRIPT" |
| 229 | + if [ -f "$FULL" ]; then |
| 230 | + echo -n " [*] Redeploying /$CTX... " |
| 231 | + set +e |
| 232 | + timeout 90 bash "$FULL" "$TOMCAT_HOME" >/dev/null 2>&1 |
| 233 | + RC=$? |
| 234 | + set -e |
| 235 | + [ $RC -eq 0 ] && echo "✓" || echo "✗ (exit $RC)" |
| 236 | + else |
| 237 | + echo " [SKIP] /$CTX — no deploy script" |
| 238 | + fi |
| 239 | + done |
| 240 | + |
| 241 | + echo "" |
| 242 | + echo " [*] Restarting Tomcat..." |
| 243 | + if [ -x "$TOMCAT_HOME/bin/shutdown.sh" ]; then |
| 244 | + "$TOMCAT_HOME/bin/shutdown.sh" >/dev/null 2>&1 || true |
| 245 | + sleep 4 |
| 246 | + "$TOMCAT_HOME/bin/startup.sh" >/dev/null 2>&1 |
| 247 | + else |
| 248 | + sudo systemctl restart tomcat 2>/dev/null || true |
| 249 | + fi |
| 250 | + echo " [*] Waiting 10s for Tomcat to load contexts..." |
| 251 | + sleep 10 |
| 252 | + |
| 253 | + echo "" |
| 254 | + echo " ── Re-verify ──" |
| 255 | + echo "" |
| 256 | + FIXED=0; STILL=0 |
| 257 | + for MOD in "${MODULES[@]}"; do |
| 258 | + IFS='|' read -r CTX SCRIPT CLASS PORT DB <<< "$MOD" |
| 259 | + CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 3 "http://localhost:8080/$CTX/" 2>/dev/null || echo "000") |
| 260 | + if [[ "$CODE" =~ ^(200|302)$ ]]; then |
| 261 | + echo " [✓] /$CTX — HTTP $CODE" |
| 262 | + FIXED=$((FIXED+1)) |
| 263 | + else |
| 264 | + echo " [✗] /$CTX — HTTP $CODE" |
| 265 | + STILL=$((STILL+1)) |
| 266 | + fi |
| 267 | + done |
| 268 | + echo "" |
| 269 | + info "Fixed: $FIXED | Still failing: $STILL" |
| 270 | + |
| 271 | + if [ "$STILL" -gt 0 ]; then |
| 272 | + echo "" |
| 273 | + echo " ── Tomcat Error Logs ──" |
| 274 | + echo "" |
| 275 | + for LOG in "$TOMCAT_HOME/logs/catalina.out" "$TOMCAT_HOME/logs/localhost.$(date +%Y-%m-%d).log"; do |
| 276 | + if [ -f "$LOG" ]; then |
| 277 | + ERRORS=$(tail -80 "$LOG" 2>/dev/null | grep -i "SEVERE\|ERROR\|exception" | grep -v "^$" | tail -8) |
| 278 | + if [ -n "$ERRORS" ]; then |
| 279 | + echo " From $(basename "$LOG"):" |
| 280 | + echo "$ERRORS" | sed 's/^/ /' |
| 281 | + echo "" |
| 282 | + fi |
| 283 | + fi |
| 284 | + done |
| 285 | + fi |
| 286 | +else |
| 287 | + pass "All $HTTP_OK endpoints responding — no fix needed" |
| 288 | +fi |
| 289 | + |
| 290 | +# ───────────────────────────────────────────────────────────────────────────── |
| 291 | +echo "" |
| 292 | +echo "╔═══════════════════════════════════════════════════════════════════════════╗" |
| 293 | +printf "║ Results: PASS=%-3d WARN=%-3d FAIL=%-3d ║\n" "$PASS" "$WARN" "$FAIL" |
| 294 | +if [ "$FAIL" -eq 0 ]; then |
| 295 | + echo "║ ✓ All checks passed ║" |
| 296 | +else |
| 297 | + echo "║ Recommended: ║" |
| 298 | + echo "║ 1. bash scripts/compile-all-modules.sh ║" |
| 299 | + echo "║ 2. bash deploy-all.sh ║" |
| 300 | + echo "║ 3. $TOMCAT_HOME/bin/shutdown.sh && sleep 3 && $TOMCAT_HOME/bin/startup.sh" |
| 301 | + echo "║ 4. bash scripts/frontend-diagnosis.sh (re-run) ║" |
| 302 | +fi |
| 303 | +echo "╚═══════════════════════════════════════════════════════════════════════════╝" |
| 304 | +echo "" |
0 commit comments