#!/bin/bash set -euo pipefail LIVE_PACKAGE=${1:?usage: smoke-fnos-package.sh liverecorder.fpk postgresql-service.fpk [temporary-directory]} POSTGRES_PACKAGE=${2:?usage: smoke-fnos-package.sh liverecorder.fpk postgresql-service.fpk [temporary-directory]} SMOKE_TMP_ROOT="${3:-${LIVERECORDER_SMOKE_TMPDIR:-${TMPDIR:-/tmp}}}" mkdir -p "$SMOKE_TMP_ROOT" SMOKE_TMP_ROOT=$(CDPATH= cd -- "$SMOKE_TMP_ROOT" && pwd) WORK_DIR=$(mktemp -d "${SMOKE_TMP_ROOT%/}/liverecorder-shared-stack-smoke.XXXXXX") STATE_DIR=$(mktemp -d "${TMPDIR:-/tmp}/liverecorder-stack-state.XXXXXX") LIVE_PACKAGE_ROOT="$WORK_DIR/live-package" LIVE_APP_ROOT="$WORK_DIR/live-app" LIVE_DATA_ROOT="$STATE_DIR/live-var" LIVE_VOLUME_ROOT="$WORK_DIR/live-volume" PG_PACKAGE_ROOT="$WORK_DIR/postgres-package" PG_APP_ROOT="$WORK_DIR/postgres-app" PG_DATA_ROOT="$STATE_DIR/postgres-var" PG_VOLUME_ROOT="$WORK_DIR/postgres-volume" LIVE_PORT=${LIVERECORDER_SMOKE_PORT:-19580} PG_API_PORT=${POSTGRES_SERVICE_SMOKE_API_PORT:-19533} PG_PORT=${POSTGRES_SERVICE_SMOKE_PG_PORT:-19532} LIVE_CONTROL="$LIVE_PACKAGE_ROOT/cmd/main" PG_CONTROL="$PG_PACKAGE_ROOT/cmd/main" ADMIN_PASSWORD='LiveRecorder-Smoke-2026!' PG_ADMIN_PASSWORD='Postgres-Admin-Smoke-2026!' ENROLLMENT_TOKEN='Postgres-Enrollment-Smoke-2026!' MEDIA_PATH="${PATH:-/usr/local/bin:/usr/bin:/bin}" NODEJS_ROOT="$WORK_DIR/nodejs-v22-target" NODEJS_BIN="${NODEJS_SMOKE_BIN:-$(type -P node)}" mkdir -p "$NODEJS_ROOT/bin" ln -s "$NODEJS_BIN" "$NODEJS_ROOT/bin/node" if ! PATH="$MEDIA_PATH" command -v ffmpeg >/dev/null 2>&1 || \ ! PATH="$MEDIA_PATH" command -v ffprobe >/dev/null 2>&1; then mkdir -p "$WORK_DIR/system-media-stubs" ln -s "$(type -P true)" "$WORK_DIR/system-media-stubs/ffmpeg" ln -s "$(type -P true)" "$WORK_DIR/system-media-stubs/ffprobe" MEDIA_PATH="$WORK_DIR/system-media-stubs:$MEDIA_PATH" fi run_live_control() { TRIM_APPDEST="$LIVE_APP_ROOT" TRIM_PKGVAR="$LIVE_DATA_ROOT" \ TRIM_APPDEST_VOL="$LIVE_VOLUME_ROOT" TRIM_SERVICE_PORT="$LIVE_PORT" \ POSTGRES_SERVICE_API="http://127.0.0.1:$PG_API_PORT" NODEJS_ROOT="$NODEJS_ROOT" \ PATH="$MEDIA_PATH" "$LIVE_CONTROL" "$@" } run_postgres_control() { TRIM_APPDEST="$PG_APP_ROOT" TRIM_PKGVAR="$PG_DATA_ROOT" \ TRIM_APPDEST_VOL="$PG_VOLUME_ROOT" TRIM_SERVICE_PORT="$PG_API_PORT" \ POSTGRES_SERVICE_PORT="$PG_PORT" "$PG_CONTROL" "$@" } cleanup() { status=$? if [ -x "$LIVE_CONTROL" ]; then run_live_control stop >/dev/null 2>&1 || true; fi if [ -x "$PG_CONTROL" ]; then run_postgres_control stop >/dev/null 2>&1 || true; fi if [ "$status" -ne 0 ]; then printf '%s\n' 'fnOS shared-stack smoke test failed; service logs follow:' >&2 for log_file in \ "$PG_DATA_ROOT/log/postgresql.log" "$PG_DATA_ROOT/log/postgres-service.log" \ "$LIVE_DATA_ROOT/log/liverecorder.log"; do if [ -f "$log_file" ]; then printf '%s\n' "--- $log_file ---" >&2 tail -n 160 "$log_file" >&2 || true fi done fi rm -rf -- "$WORK_DIR" rm -rf -- "$STATE_DIR" return "$status" } trap cleanup EXIT HUP INT TERM mkdir -p "$LIVE_PACKAGE_ROOT" "$LIVE_APP_ROOT" "$LIVE_VOLUME_ROOT" \ "$PG_PACKAGE_ROOT" "$PG_APP_ROOT" "$PG_VOLUME_ROOT" tar -xzf "$POSTGRES_PACKAGE" -C "$PG_PACKAGE_ROOT" tar -xzf "$PG_PACKAGE_ROOT/app.tgz" -C "$PG_APP_ROOT" rm -f "$PG_PACKAGE_ROOT/app.tgz" tar -xzf "$LIVE_PACKAGE" -C "$LIVE_PACKAGE_ROOT" tar -xzf "$LIVE_PACKAGE_ROOT/app.tgz" -C "$LIVE_APP_ROOT" rm -f "$LIVE_PACKAGE_ROOT/app.tgz" test ! -e "$LIVE_APP_ROOT/runtime/usr/lib/postgresql" test ! -e "$LIVE_APP_ROOT/runtime/usr/share/postgresql" test ! -e "$LIVE_APP_ROOT/runtime/lib/libLLVM-14.so.1" test ! -e "$LIVE_APP_ROOT/runtime/lib/libz3.so.4" test ! -e "$LIVE_APP_ROOT/runtime/bin/node" TRIM_PKGVAR="$PG_DATA_ROOT" \ wizard_postgres_admin_password="$PG_ADMIN_PASSWORD" \ wizard_postgres_admin_password_confirm="$PG_ADMIN_PASSWORD" \ wizard_postgres_enrollment_token="$ENROLLMENT_TOKEN" \ wizard_postgres_enrollment_token_confirm="$ENROLLMENT_TOKEN" \ "$PG_PACKAGE_ROOT/cmd/install_callback" TRIM_PKGVAR="$LIVE_DATA_ROOT" \ wizard_admin_password="$ADMIN_PASSWORD" \ wizard_admin_password_confirm="$ADMIN_PASSWORD" \ wizard_postgres_enrollment_token="$ENROLLMENT_TOKEN" \ "$LIVE_PACKAGE_ROOT/cmd/install_callback" run_postgres_control start run_postgres_control status curl -fsS "http://127.0.0.1:$PG_API_PORT/health/ready" | grep -q '"status":"ready"' run_live_control start run_live_control status BASE_URL="http://127.0.0.1:$LIVE_PORT" curl -fsS "$BASE_URL/health/ready" | grep -q '"status":"ready"' curl -fsS "$BASE_URL/" | grep -q '
' CREDENTIALS="$LIVE_DATA_ROOT/postgres-client.conf" test -s "$CREDENTIALS" test "$(stat -c '%a' "$CREDENTIALS")" = "600" grep -q '^host=127\.0\.0\.1$' "$CREDENTIALS" grep -q "^port=$PG_PORT$" "$CREDENTIALS" grep -q '^database=appdb_liverecorder_' "$CREDENTIALS" grep -q '^username=app_liverecorder_' "$CREDENTIALS" test ! -e "$LIVE_DATA_ROOT/postgres" test ! -e "$LIVE_DATA_ROOT/postgres-enrollment-token.seed" login_response=$(curl -fsS -H 'Content-Type: application/json' \ --data "{\"username\":\"admin\",\"password\":\"$ADMIN_PASSWORD\"}" \ "$BASE_URL/api/auth/login") token=$(printf '%s' "$login_response" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p') test -n "$token" settings_response=$(curl -fsS -H "Authorization: Bearer $token" "$BASE_URL/api/settings") expected_record_root="$LIVE_VOLUME_ROOT/@appshare/liverecorder/records" printf '%s' "$settings_response" | grep -Fq "\"outputRoot\":\"$expected_record_root\"" session_page_response=$(curl -fsS -H "Authorization: Bearer $token" \ "$BASE_URL/api/record-sessions/page?skip=0&take=12&state=all") printf '%s' "$session_page_response" | grep -q '"items":\[\]' printf '%s' "$session_page_response" | grep -q '"totalCount":0' printf '%s' "$session_page_response" | grep -q '"take":12' filtered_session_page_response=$(curl -fsS -H "Authorization: Bearer $token" \ "$BASE_URL/api/record-sessions/page?skip=0&take=12&state=active&search=needle") printf '%s' "$filtered_session_page_response" | grep -q '"totalCount":0' runtime_libs="$LIVE_APP_ROOT/runtime/lib" ca_bundle="$LIVE_APP_ROOT/runtime/etc/ssl/certs/ca-certificates.crt" node_bin="$NODEJS_ROOT/bin/node" curl_bin="$LIVE_APP_ROOT/runtime/bin/curl" signer="$LIVE_APP_ROOT/server/Platforms/Douyin/Signing/sign-xbogus.js" LD_LIBRARY_PATH="$runtime_libs" "$node_bin" --version | grep -Eq '^v[0-9]+\.' signature=$(LD_LIBRARY_PATH="$runtime_libs" "$node_bin" "$signer" \ 'aid=6383&device_platform=web&room_id=1' 'Mozilla/5.0 LiveRecorder fnOS shared-stack smoke test') test -n "$signature" LD_LIBRARY_PATH="$runtime_libs" SSL_CERT_FILE="$ca_bundle" CURL_CA_BUNDLE="$ca_bundle" \ "$curl_bin" -fsS "$BASE_URL/health/ready" >/dev/null run_live_control stop if run_live_control status; then printf '%s\n' 'Live Recorder remained running after stop' >&2 exit 1 fi run_postgres_control status curl -fsS "http://127.0.0.1:$PG_API_PORT/health/ready" | grep -q '"status":"ready"' run_live_control start run_live_control status curl -fsS "$BASE_URL/health/ready" | grep -q '"status":"ready"' run_live_control stop run_postgres_control stop rm -f "$CREDENTIALS" "$LIVE_DATA_ROOT/postgres-enrollment-token.seed" mkdir -p "$LIVE_DATA_ROOT/postgres" printf '15\n' >"$LIVE_DATA_ROOT/postgres/PG_VERSION" if run_live_control start; then printf '%s\n' 'Live Recorder unexpectedly fell back to a legacy private PostgreSQL database' >&2 exit 1 fi grep -q '无法连接 PostgreSQL 共享服务或取得数据库凭据,应用不会启动' \ "$LIVE_DATA_ROOT/log/liverecorder.log" printf '%s\n' 'fnOS shared-stack smoke test passed: independent PostgreSQL stayed running, Live Recorder enrolled, persisted credentials and restarted without Docker'