build_router_package.sh 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #!/usr/bin/env sh
  2. set -eu
  3. SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
  4. APP_DIR="$SCRIPT_DIR"
  5. PKG_ROOT_NAME=${PKG_ROOT_NAME:-vmess}
  6. OUT_TAR=${OUT_TAR:-"$APP_DIR/vmess.tar.gz"}
  7. TMP_DIR=${TMP_DIR:-"/tmp/vmess_pkg.$$"}
  8. ROUTER_CONF=${ROUTER_CONF:-"$APP_DIR/config_router.conf"}
  9. HTTP_SCRIPT=${HTTP_SCRIPT:-"$APP_DIR/scripts/router_local_http.sh"}
  10. UPDATE_SCRIPT=${UPDATE_SCRIPT:-"$APP_DIR/scripts/router_local_update.sh"}
  11. # Defaults aligned with current repo layout.
  12. BUSYBOX_SRC=${BUSYBOX_SRC:-"$APP_DIR/busybox/busybox-armv7l"}
  13. CFST_SRC_DIR=${CFST_SRC_DIR:-"$APP_DIR/cfst_linux_armv5"}
  14. VERBOSE=${VERBOSE:-1}
  15. log() {
  16. if [ "${VERBOSE}" = "1" ]; then
  17. printf '%s\n' "$*"
  18. fi
  19. }
  20. warn() {
  21. printf '[warn] %s\n' "$*" >&2
  22. }
  23. err() {
  24. printf '[error] %s\n' "$*" >&2
  25. exit 1
  26. }
  27. require_file() {
  28. p="$1"
  29. [ -f "$p" ] || err "required file missing: $p"
  30. }
  31. require_dir() {
  32. p="$1"
  33. [ -d "$p" ] || err "required directory missing: $p"
  34. }
  35. parse_conf_var() {
  36. conf="$1"
  37. key="$2"
  38. if [ ! -r "$conf" ]; then
  39. return 1
  40. fi
  41. sed -n "s|^${key}=\"\\(.*\\)\"$|\\1|p" "$conf" | head -n 1
  42. }
  43. resolve_from_conf_dir() {
  44. conf="$1"
  45. val="$2"
  46. conf_dir=$(CDPATH= cd -- "$(dirname -- "$conf")" && pwd)
  47. case "$val" in
  48. "") printf '%s\n' "" ;;
  49. /*) printf '%s\n' "$val" ;;
  50. *) printf '%s/%s\n' "$conf_dir" "$val" ;;
  51. esac
  52. }
  53. check_busybox_httpd() {
  54. bb="$1"
  55. if [ ! -f "$bb" ]; then
  56. warn "BusyBox binary missing: $bb"
  57. return 1
  58. fi
  59. if [ -x "$bb" ] && "$bb" --list 2>/dev/null | grep '^httpd$' >/dev/null 2>&1; then
  60. return 0
  61. fi
  62. # 跨平台构建(例如在 macOS 上打包 Linux ARM ELF 二进制),回退到静态字符串检查
  63. if strings "$bb" 2>/dev/null | grep -q 'httpd'; then
  64. return 0
  65. fi
  66. warn "BusyBox has no httpd applet: $bb"
  67. return 1
  68. }
  69. log "[pkg] app dir: $APP_DIR"
  70. log "[pkg] output: $OUT_TAR"
  71. require_file "$ROUTER_CONF"
  72. require_file "$HTTP_SCRIPT"
  73. require_file "$UPDATE_SCRIPT"
  74. require_dir "$CFST_SRC_DIR"
  75. require_file "$BUSYBOX_SRC"
  76. # 基础文件校验通过后再安全初始化临时目录与 trap
  77. case "$TMP_DIR" in
  78. ""|"/"|"/tmp"|"/var"|"$APP_DIR"|"$HOME") err "Unsafe TMP_DIR: '$TMP_DIR'" ;;
  79. esac
  80. cleanup() {
  81. rm -rf "$TMP_DIR"
  82. }
  83. trap cleanup EXIT INT TERM
  84. bb_from_conf_raw=$(parse_conf_var "$ROUTER_CONF" "BUSYBOX_BIN" || true)
  85. if [ -n "${bb_from_conf_raw:-}" ]; then
  86. bb_from_conf=$(resolve_from_conf_dir "$ROUTER_CONF" "$bb_from_conf_raw")
  87. if [ "$bb_from_conf" != "$BUSYBOX_SRC" ]; then
  88. warn "BUSYBOX_BIN in conf points to: $bb_from_conf_raw -> $bb_from_conf"
  89. warn "packaging source busybox is: $BUSYBOX_SRC"
  90. warn "if needed, set BUSYBOX_SRC to keep packaging and runtime consistent"
  91. fi
  92. fi
  93. if ! check_busybox_httpd "$BUSYBOX_SRC"; then
  94. warn "continuing packaging, but router HTTP may fail later"
  95. fi
  96. mkdir -p "$TMP_DIR/$PKG_ROOT_NAME/scripts" "$TMP_DIR/$PKG_ROOT_NAME/cfst"
  97. cp "$ROUTER_CONF" "$TMP_DIR/$PKG_ROOT_NAME/config_router.conf"
  98. cp "$HTTP_SCRIPT" "$TMP_DIR/$PKG_ROOT_NAME/scripts/router_local_http.sh"
  99. cp "$UPDATE_SCRIPT" "$TMP_DIR/$PKG_ROOT_NAME/scripts/router_local_update.sh"
  100. cp "$BUSYBOX_SRC" "$TMP_DIR/$PKG_ROOT_NAME/busybox_armv7l"
  101. cp -R "$CFST_SRC_DIR"/. "$TMP_DIR/$PKG_ROOT_NAME/cfst/"
  102. chmod +x \
  103. "$TMP_DIR/$PKG_ROOT_NAME/busybox_armv7l" \
  104. "$TMP_DIR/$PKG_ROOT_NAME/scripts/router_local_http.sh" \
  105. "$TMP_DIR/$PKG_ROOT_NAME/scripts/router_local_update.sh" || true
  106. rm -f "$OUT_TAR"
  107. COPYFILE_DISABLE=1 tar --exclude='.DS_Store' --exclude='._*' -czf "$OUT_TAR" -C "$TMP_DIR" "$PKG_ROOT_NAME"
  108. log "[pkg] tar created: $OUT_TAR"
  109. log "[pkg] tar size: $(ls -lh "$OUT_TAR" | awk '{print $5}')"
  110. log "[pkg] tar content preview:"
  111. tar -tzf "$OUT_TAR" | sed -n '1,120p'
  112. if ! tar -tzf "$OUT_TAR" | grep "^$PKG_ROOT_NAME/busybox_armv7l$" >/dev/null; then
  113. err "package validation failed: busybox_armv7l missing"
  114. fi
  115. if ! tar -tzf "$OUT_TAR" | grep "^$PKG_ROOT_NAME/scripts/router_local_http.sh$" >/dev/null; then
  116. err "package validation failed: router_local_http.sh missing"
  117. fi
  118. if ! tar -tzf "$OUT_TAR" | grep "^$PKG_ROOT_NAME/cfst/cfst$" >/dev/null; then
  119. err "package validation failed: cfst binary missing"
  120. fi
  121. log "[pkg] validation passed"