| #!/bin/sh |
| set -e |
|
|
| DB_ROOT_PASSWORD="123456" |
| DB_NAME="dnsmgr" |
| DB_USER="dnsmgr" |
| DB_PASSWORD="123456" |
| DB_PORT=3306 |
| DB_PREFIX="dnsmgr_" |
| ADMIN_USER="admin" |
| ADMIN_PASSWORD="123456" |
| INIT_FLAG="/var/lib/mysql/.initialized" |
|
|
| |
| |
| if [ -d "/data" ]; then |
| echo "=== Persistent storage detected at /data ===" |
| PERSISTENT=true |
|
|
| |
| mkdir -p /data/mysql |
| mkdir -p /data/runtime/temp /data/runtime/cache /data/runtime/session /data/runtime/log |
| mkdir -p /data/public/storage |
|
|
| |
| chown -R mysql:mysql /data/mysql |
| chown -R nginx:nginx /data/runtime /data/public |
|
|
| |
| if [ ! -L /var/lib/mysql ]; then |
| echo " Linking /var/lib/mysql -> /data/mysql" |
| rm -rf /var/lib/mysql |
| ln -sf /data/mysql /var/lib/mysql |
| fi |
|
|
| |
| if [ ! -L /app/www/runtime ]; then |
| echo " Linking /app/www/runtime -> /data/runtime" |
| rm -rf /app/www/runtime |
| ln -sf /data/runtime /app/www/runtime |
| fi |
|
|
| |
| if [ ! -L /app/www/public/storage ]; then |
| echo " Linking /app/www/public/storage -> /data/public/storage" |
| rm -rf /app/www/public/storage |
| ln -sf /data/public/storage /app/www/public/storage |
| fi |
|
|
| echo "=== Persistent storage ready ===" |
| else |
| echo "=== No persistent volume (/data), running ephemerally ===" |
| PERSISTENT=false |
| fi |
|
|
| if [ ! -f "$INIT_FLAG" ]; then |
| echo "=== Initializing MariaDB ===" |
|
|
| mysql_install_db --datadir=/var/lib/mysql --user=mysql >/dev/null 2>&1 |
|
|
| mysqld --datadir=/var/lib/mysql --user=mysql --skip-networking & |
| MYSQL_PID=$! |
|
|
| for i in $(seq 1 30); do |
| if mysql -u root --socket=/run/mysqld/mysqld.sock -e "SELECT 1" >/dev/null 2>&1; then |
| break |
| fi |
| sleep 1 |
| done |
|
|
| mysql -u root --socket=/run/mysqld/mysqld.sock <<EOSQL |
| FLUSH PRIVILEGES; |
| CREATE USER IF NOT EXISTS 'root'@'127.0.0.1' IDENTIFIED BY '${DB_ROOT_PASSWORD}'; |
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION; |
| CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; |
| CREATE USER IF NOT EXISTS '${DB_USER}'@'127.0.0.1' IDENTIFIED BY '${DB_PASSWORD}'; |
| GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'127.0.0.1'; |
| EOSQL |
|
|
| echo "=== Creating tables ===" |
| mysql -u root --socket=/run/mysqld/mysqld.sock "${DB_NAME}" < /app/www/app/sql/install.sql |
|
|
| echo "=== Creating admin user ===" |
| SYS_KEY=$(php -r "echo bin2hex(random_bytes(8));") |
| ADMIN_HASH=$(php -r "echo password_hash('${ADMIN_PASSWORD}', PASSWORD_DEFAULT);") |
| mysql -u root --socket=/run/mysqld/mysqld.sock "${DB_NAME}" <<EOSQL |
| REPLACE INTO \`${DB_PREFIX}config\` VALUES ('sys_key', '${SYS_KEY}'); |
| INSERT INTO \`${DB_PREFIX}user\` (\`username\`,\`password\`,\`level\`,\`regtime\`,\`lasttime\`,\`status\`) VALUES ('${ADMIN_USER}', '${ADMIN_HASH}', 2, NOW(), NOW(), 1); |
| EOSQL |
|
|
| echo "=== Setting root password ===" |
| mysql -u root --socket=/run/mysqld/mysqld.sock <<EOSQL |
| ALTER USER 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASSWORD}'; |
| FLUSH PRIVILEGES; |
| EOSQL |
|
|
| kill $MYSQL_PID 2>/dev/null |
| wait $MYSQL_PID 2>/dev/null || true |
|
|
| touch "$INIT_FLAG" |
| echo "=== MariaDB initialized ===" |
| fi |
|
|
| if [ ! -f /app/www/.env ]; then |
| cat > /app/www/.env <<EOF |
| APP_DEBUG = true |
| |
| [APP] |
| DEFAULT_TIMEZONE = Asia/Shanghai |
| |
| [DATABASE] |
| TYPE = mysql |
| HOSTNAME = 127.0.0.1 |
| DATABASE = ${DB_NAME} |
| USERNAME = ${DB_USER} |
| PASSWORD = ${DB_PASSWORD} |
| HOSTPORT = ${DB_PORT} |
| CHARSET = utf8mb4 |
| PREFIX = ${DB_PREFIX} |
| DEBUG = true |
| |
| [LANG] |
| default_lang = zh-cn |
| EOF |
| echo "=== .env written ===" |
| fi |
|
|
| |
| cat > /app/www/public/check.php <<'PHPEOF' |
| <?php |
| header('Content-Type: text/plain; charset=utf-8'); |
| echo "===== PHP Probe v2 =====\n\n"; |
| echo "PHP version: " . PHP_VERSION . "\n"; |
| echo "PHP-FPM user: " . (function_exists('exec') ? exec('whoami') : 'N/A') . "\n"; |
|
|
| echo "\n--- Runtime dirs ---\n"; |
| $runtime = dirname(__DIR__) . '/runtime'; |
| $dirs = ['temp', 'cache', 'session', 'log']; |
| foreach ($dirs as $d) { |
| $p = $runtime . '/' . $d; |
| $exists = is_dir($p) ? 'dir' : (is_file($p) ? 'FILE' : 'NOT_EXIST'); |
| $writable = is_writable($p) ? 'WRITABLE' : 'NOT_WRITABLE'; |
| $perms = substr(sprintf('%o', fileperms($p)), -4); |
| $owner = function_exists('posix_getpwuid') ? posix_getpwuid(fileowner($p))['name'] ?? fileowner($p) : fileowner($p); |
| echo " $d: $exists | $writable | perms=$perms | owner=$owner\n"; |
| } |
|
|
| echo "\n--- Test template compile ---\n"; |
| $tmpFile = $runtime . '/temp/_test_compile.php'; |
| $result = @file_put_contents($tmpFile, '<?php echo "ok";'); |
| if ($result === false) { |
| echo " WRITE FAILED: " . error_get_last()['message'] . "\n"; |
| } else { |
| echo " Write OK (" . $result . " bytes)\n"; |
| @unlink($tmpFile); |
| } |
|
|
| echo "\n--- .env ---\n"; |
| $f = dirname(__DIR__) . '/.env'; |
| echo file_exists($f) ? "exists\n" . file_get_contents($f) : "MISSING\n"; |
|
|
| echo "\n--- Database ---\n"; |
| try { |
| $p = new PDO("mysql:host=127.0.0.1;port=3306;dbname=dnsmgr;charset=utf8mb4", "dnsmgr", "123456", [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_TIMEOUT => 3]); |
| echo "DB OK\nTables: " . implode(", ", $p->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN)) . "\n"; |
| echo "Config:\n"; foreach ($p->query("SELECT `key`,`value` FROM dnsmgr_config") as $r) { echo " {$r['key']}={$r['value']}\n"; } |
| echo "Users:\n"; foreach ($p->query("SELECT id,username,level,status FROM dnsmgr_user") as $r) { echo " {$r['id']} {$r['username']} lv{$r['level']} st{$r['status']}\n"; } |
| } catch (Exception $e) { echo "DB ERROR: " . $e->getMessage() . "\n"; } |
|
|
| echo "\n--- PHP-FPM error log (last 20 lines) ---\n"; |
| $errorLog = ini_get('error_log'); |
| if ($errorLog && is_file($errorLog)) { |
| $lines = array_slice(file($errorLog), -20); |
| foreach ($lines as $l) echo " $l"; |
| } else { |
| echo " error_log not configured or not found: " . ($errorLog ?: 'none') . "\n"; |
| } |
|
|
| echo "\n--- Runtime log (last 10 lines) ---\n"; |
| $logFile = $runtime . '/log/' . date('Y-m-d') . '.log'; |
| if (is_file($logFile)) { |
| $lines = array_slice(file($logFile), -10); |
| foreach ($lines as $l) echo " $l"; |
| } else { |
| echo " no log file at $logFile\n"; |
| } |
|
|
| echo "\n===== Done =====\n"; |
| PHPEOF |
| chown nginx:nginx /app/www/public/check.php 2>/dev/null || true |
| echo "=== check.php created ===" |
|
|
| cat > /app/www/public/rtest.php <<'PHPEOF' |
| <?php |
| header('Content-Type: text/plain; charset=utf-8'); |
|
|
| $orig = $_SERVER; |
|
|
| $_SERVER['REQUEST_URI'] = '/login'; |
| $_SERVER['REQUEST_METHOD'] = 'GET'; |
| $_SERVER['SCRIPT_NAME'] = '/index.php'; |
| $_SERVER['SCRIPT_FILENAME'] = '/app/www/public/index.php'; |
| $_SERVER['PHP_SELF'] = '/index.php'; |
| $_SERVER['QUERY_STRING'] = ''; |
| $_SERVER['HTTPS'] = 'off'; |
| $_SERVER['PATH_INFO'] = ''; |
| $_SERVER['ORIG_PATH_INFO'] = ''; |
| $_SERVER['DOCUMENT_ROOT'] = dirname(__DIR__) . '/public'; |
| $_SERVER['SERVER_NAME'] = 'localhost'; |
| $_SERVER['SERVER_PORT'] = '8081'; |
| $_SERVER['HTTP_HOST'] = 'localhost:8081'; |
| $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; |
| unset($_SERVER['argv']); |
|
|
| try { |
| require dirname(__DIR__) . '/vendor/autoload.php'; |
| $app = new \think\App(dirname(__DIR__)); |
| $http = $app->http; |
| |
| // 1. Show pathinfo resolution |
| echo "=== Pathinfo ===\n"; |
| $req = $app->make('request', [], true); |
| echo "PATH_INFO: " . var_export($req->server('PATH_INFO'), true) . "\n"; |
| echo "ORIG_PATH_INFO: " . var_export($req->server('ORIG_PATH_INFO'), true) . "\n"; |
| echo "REQUEST_URI: " . var_export($req->server('REQUEST_URI'), true) . "\n"; |
| echo "SCRIPT_NAME: " . var_export($req->server('SCRIPT_NAME'), true) . "\n"; |
| echo "PHP_SELF: " . var_export($req->server('PHP_SELF'), true) . "\n"; |
| echo "pathinfo(): " . $req->pathinfo() . "\n"; |
| echo "baseUrl(): " . $req->baseUrl() . "\n"; |
| echo "baseFile(): " . $req->baseFile() . "\n\n"; |
| |
| // 2. Load routes manually then list |
| echo "=== Routes ===\n"; |
| $routePath = $app->getRootPath() . 'route/'; |
| $files = glob($routePath . '*.php'); |
| if ($files) { |
| foreach ($files as $file) { |
| include $file; |
| } |
| } |
| $routeService = $app->make('route'); |
| $rules = $routeService->getRuleList(); |
| echo "Total route rules: " . count($rules) . "\n"; |
| foreach ($rules as $r) { |
| $method = $r['method'] ?? '*'; |
| $rule = $r['rule'] ?? '?'; |
| $route = $r['route']; |
| if ($route instanceof \Closure) { |
| $route = 'Closure'; |
| } elseif (is_array($route)) { |
| $route = json_encode($route); |
| } elseif (is_object($route)) { |
| $route = get_class($route); |
| } |
| echo " $method $rule -> $route\n"; |
| } |
| echo "\n"; |
| |
| // 3. Now run the dispatch with /login PATH_INFO |
| $_SERVER['PATH_INFO'] = '/login'; |
| echo "=== Dispatch /login ===\n"; |
| $response = $http->run(); |
| |
| echo "Code: " . $response->getCode() . "\n"; |
| echo "Class: " . get_class($response) . "\n"; |
| echo "Headers:\n"; |
| foreach ($response->getHeader() as $k => $v) { |
| echo " $k: $v\n"; |
| } |
| echo "Content (" . strlen($response->getContent()) . " bytes): " . substr($response->getContent(), 0, 500) . "\n"; |
| |
| } catch (\Throwable $e) { |
| echo "EXCEPTION: " . get_class($e) . ": " . $e->getMessage() . "\n"; |
| echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n"; |
| echo $e->getTraceAsString() . "\n"; |
| } |
| $_SERVER = $orig; |
| PHPEOF |
| chown nginx:nginx /app/www/public/rtest.php 2>/dev/null || true |
| echo "=== rtest.php created ===" |
|
|
| exec "$@" |
|
|