- service.sh: split service_remove into internal (no prompts) and interactive versions to prevent 'eternal wait' when installing new strategy. Install now calls service_remove_internal > /dev/null instead of service_remove. Also filter strategy list to general*.sh only to avoid clutter. Systemd ExecStart now points to run_strategy.sh <name> consistently. - run_strategy.sh: add SIGTERM/SIGINT trap cleanup_strategy() that kills nfqws and cleans up firewall. Prevents stale nfqws/firewall rules after autotest kill. Also handles nfqws exit gracefully with final cleanup. - autotest.sh: rewritten to test strategies by config name (not wrapper filename). Stop now sends SIGTERM to wrapper (which triggers trap cleanup) instead of bare kill. Added extra sleep after stop to let trap fire. Auto-install ExecStart fixed to run_strategy.sh <strategy>. - setup.sh: added libmnl-dev and zlib1g-dev to Ubuntu/Debian dependency install to prevent build failures (missing libmnl/libmnl.h and zlib.h). - general*.sh: removed UTF-8 BOM (0xEF 0xBB 0xBF) that caused 'exec format error' when running scripts on Linux. All 19 wrappers cleaned. - ensure_wrappers.sh: always rewrite wrappers to ensure no stale BOM or paths. Fixes: eternal wait on menu option 1, nfqws build failure, stale processes after test.
223 lines
6.2 KiB
Bash
Executable File
223 lines
6.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# update.sh - Full auto-pipeline: sync upstream → update → build → test → install
|
|
# Version: 2.0
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/lib/functions.sh"
|
|
|
|
LOCAL_VERSION_FILE="$SCRIPT_DIR/.service/version.txt"
|
|
UPDATE_LOG="$SCRIPT_DIR/.service/update.log"
|
|
|
|
mkdir -p "$SCRIPT_DIR/.service"
|
|
|
|
log_msg() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$UPDATE_LOG"
|
|
}
|
|
|
|
# Check if nfqws binary is healthy
|
|
verify_nfqws() {
|
|
local bin="$BIN_DIR/nfqws"
|
|
if [[ ! -x "$bin" ]]; then
|
|
log_msg "[FAIL] nfqws binary missing or not executable: $bin"
|
|
return 1
|
|
fi
|
|
if ! "$bin" --help >/dev/null 2>&1; then
|
|
log_msg "[FAIL] nfqws binary does not run (segfault?)"
|
|
return 1
|
|
fi
|
|
log_msg "[OK] nfqws binary verified."
|
|
return 0
|
|
}
|
|
|
|
# Rebuild nfqws
|
|
rebuild_nfqws() {
|
|
log_msg "[*] Rebuilding nfqws..."
|
|
if bash "$SCRIPT_DIR/install_nfqws.sh"; then
|
|
verify_nfqws
|
|
else
|
|
log_msg "[FAIL] Build script failed."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Run autotest pipeline
|
|
run_pipeline_autotest() {
|
|
log_msg "[*] Running auto-test pipeline..."
|
|
if command -v systemctl >/dev/null 2>&1; then
|
|
systemctl stop zapret.service 2>/dev/null || true
|
|
fi
|
|
cleanup_firewall >/dev/null 2>&1 || true
|
|
sleep 2
|
|
|
|
bash "$SCRIPT_DIR/autotest.sh" --auto && {
|
|
log_msg "[OK] Auto-test: working strategy found and installed."
|
|
return 0
|
|
} || {
|
|
log_msg "[WARN] Auto-test: no working strategy found."
|
|
return 1
|
|
}
|
|
}
|
|
|
|
# Restart systemd service
|
|
restart_service() {
|
|
if command -v systemctl >/dev/null 2>&1; then
|
|
if systemctl is-enabled zapret.service >/dev/null 2>&1; then
|
|
log_msg "[*] Restarting zapret.service..."
|
|
systemctl restart zapret.service
|
|
log_msg "[OK] Service restarted."
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Step 0: Sync upstream
|
|
do_sync() {
|
|
log_msg "[*] Step 0: Syncing upstream strategies, lists, hosts..."
|
|
bash "$SCRIPT_DIR/sync_from_upstream.sh" 2>&1 | tee -a "$UPDATE_LOG"
|
|
local sync_status=${PIPESTATUS[0]}
|
|
|
|
case "$sync_status" in
|
|
0) log_msg "[OK] Sync complete, no rebuild needed."
|
|
SYNC_REBUILD=0
|
|
;;
|
|
2) log_msg "[OK] Sync complete, REBUILD FLAGGED (new version or lists changed)."
|
|
SYNC_REBUILD=1
|
|
;;
|
|
*) log_msg "[WARN] Sync encountered errors (exit $sync_status). Continue anyway."
|
|
SYNC_REBUILD=0
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Step 1-4: Main pipeline
|
|
full_pipeline() {
|
|
local mode="${1:-interactive}"
|
|
local force="${2:-no}"
|
|
|
|
[[ "$mode" == "interactive" ]] && {
|
|
echo ""
|
|
echo "=============================================="
|
|
echo " Zapret Full Auto Pipeline v2.0"
|
|
echo " Current: $LOCAL_VERSION"
|
|
echo "=============================================="
|
|
echo ""
|
|
}
|
|
|
|
# Step 0: Always sync upstream first
|
|
do_sync
|
|
|
|
# Determine if we need to rebuild
|
|
local need_rebuild=0
|
|
if [[ "$force" == "yes" ]]; then
|
|
log_msg "[*] Force rebuild requested."
|
|
need_rebuild=1
|
|
elif [[ "${SYNC_REBUILD:-0}" -eq 1 ]]; then
|
|
log_msg "[*] Rebuild flagged by sync."
|
|
need_rebuild=1
|
|
fi
|
|
|
|
if [[ "$need_rebuild" -eq 0 ]] && [[ "$mode" == "interactive" ]]; then
|
|
read -rp "No upstream changes detected. Force rebuild + re-test? [y/N]: " ans
|
|
[[ "$ans" == [yY]* ]] && need_rebuild=1
|
|
fi
|
|
|
|
if [[ "$need_rebuild" -eq 0 ]]; then
|
|
log_msg "[*] No rebuild needed. Exiting."
|
|
exit 0
|
|
fi
|
|
|
|
# Step 1: Update version marker
|
|
log_msg "[*] Step 1: Updating version marker..."
|
|
local upstream_ver
|
|
upstream_ver=$(cat "$LOCAL_VERSION_FILE" 2>/dev/null | sed 's/LOCAL_VERSION=//' | tr -d '\\"' || echo "$LOCAL_VERSION")
|
|
echo "$upstream_ver" > "$LOCAL_VERSION_FILE"
|
|
|
|
# Step 2: Rebuild nfqws
|
|
log_msg "[*] Step 2: Rebuilding nfqws..."
|
|
if ! rebuild_nfqws; then
|
|
log_msg "[CRITICAL] Build failed. Aborting."
|
|
exit 1
|
|
fi
|
|
|
|
# Step 3: Auto-test
|
|
log_msg "[*] Step 3: Auto-testing strategies..."
|
|
run_pipeline_autotest || true
|
|
|
|
# Step 4: Restart
|
|
log_msg "[*] Step 4: Restarting service..."
|
|
restart_service
|
|
|
|
log_msg "[SUCCESS] Full pipeline complete."
|
|
|
|
[[ "$mode" == "interactive" ]] && {
|
|
echo ""
|
|
print_green "=============================================="
|
|
print_green " Pipeline Complete!"
|
|
print_green " Version: $(cat "$LOCAL_VERSION_FILE" 2>/dev/null || echo "$LOCAL_VERSION")"
|
|
print_green "=============================================="
|
|
systemctl status zapret --no-pager 2>/dev/null || true
|
|
}
|
|
}
|
|
|
|
# Non-interactive cron mode
|
|
auto_mode() {
|
|
log_msg "Auto-update started..."
|
|
log_msg "[*] Syncing upstream..."
|
|
bash "$SCRIPT_DIR/sync_from_upstream.sh" --auto 2>&1 | tee -a "$UPDATE_LOG"
|
|
local sync_status=${PIPESTATUS[0]}
|
|
|
|
if [[ "$sync_status" -ne 2 ]]; then
|
|
log_msg "No update needed or sync failed. Exiting."
|
|
exit 0
|
|
fi
|
|
|
|
log_msg "Update detected, running full pipeline..."
|
|
rebuild_nfqws || { log_msg "[FAIL] Rebuild failed."; exit 1; }
|
|
run_pipeline_autotest || true
|
|
restart_service
|
|
log_msg "Auto-update finished."
|
|
}
|
|
|
|
# CLI
|
|
MODE="interactive"
|
|
FORCE="no"
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--auto|-a) MODE="auto"; shift ;;
|
|
--force|-f) FORCE="yes"; shift ;;
|
|
--full-auto) MODE="auto"; FORCE="yes"; shift ;;
|
|
--help|-h)
|
|
cat <<EOF
|
|
Usage: sudo ./update.sh [OPTIONS]
|
|
|
|
Full pipeline: sync upstream lists/hosts/version → rebuild nfqws → test → install.
|
|
|
|
Options:
|
|
--auto, -a Non-interactive (for cron/systemd timers)
|
|
--force, -f Force rebuild even if versions match
|
|
--full-auto Same as --auto --force (always rebuild + re-test)
|
|
--help, -h Show this help
|
|
|
|
Examples:
|
|
sudo ./update.sh # interactive prompt
|
|
sudo ./update.sh --full-auto # headless, always rebuild
|
|
sudo ./update.sh --auto # headless, only if upstream changed
|
|
EOF
|
|
exit 0
|
|
;;
|
|
*) echo "Unknown: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ "$MODE" == "auto" ]]; then
|
|
if [[ "$FORCE" == "yes" ]]; then
|
|
full_pipeline auto yes
|
|
else
|
|
auto_mode
|
|
fi
|
|
else
|
|
full_pipeline interactive "$FORCE"
|
|
fi
|