host = $config['host'] ?? 'localhost'; $this->username = $config['username'] ?? 'root'; $this->password = $config['password'] ?? ''; $this->database = $config['database'] ?? 'test'; $this->port = $config['port'] ?? 3306; } public function testConnection() { $this->printHeader(); // 安全地显示连接信息(隐藏密码) $this->printConnectionInfo(); try { // 测试连接 $result = $this->connect(); $this->printSuccess($result); // 测试查询 $this->testQueries($result['pdo']); } catch (Exception $e) { $this->printError($e); return false; } $this->printFooter(); return true; } private function connect() { $start_time = microtime(true); $dsn = "mysql:host={$this->host};port={$this->port};dbname={$this->database};charset=utf8mb4"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_TIMEOUT => 5, // 5秒连接超时 ]; $pdo = new PDO($dsn, $this->username, $this->password, $options); $end_time = microtime(true); $connection_time = round(($end_time - $start_time) * 1000, 2); return [ 'pdo' => $pdo, 'connection_time' => $connection_time, 'server_version' => $pdo->getAttribute(PDO::ATTR_SERVER_VERSION), 'client_version' => $pdo->getAttribute(PDO::ATTR_CLIENT_VERSION) ]; } private function testQueries($pdo) { echo "执行测试查询...\n"; // 测试1: 简单查询 $stmt = $pdo->query("SELECT 1 as test_value, NOW() as current_time"); $result = $stmt->fetch(); echo "✅ 简单查询测试: 成功\n"; // 测试2: 显示当前用户和数据库 $stmt = $pdo->query("SELECT USER() as current_user, DATABASE() as current_database"); $info = $stmt->fetch(); echo "当前用户: {$info['current_user']}\n"; echo "当前数据库: {$info['current_database']}\n"; // 测试3: 显示进程列表(前5个) try { $stmt = $pdo->query("SHOW PROCESSLIST LIMIT 5"); $processes = $stmt->fetchAll(); echo "当前连接数: " . count($processes) . "\n"; } catch (Exception $e) { echo "⚠️ 无法查看进程列表(权限不足)\n"; } } private function printHeader() { echo "========================================\n"; echo "MySQL数据库连接测试\n"; echo "========================================\n"; } private function printConnectionInfo() { echo "连接信息:\n"; echo "主机: {$this->host}:{$this->port}\n"; echo "数据库: {$this->database}\n"; echo "用户名: {$this->username}\n"; echo "密码: " . ($this->password ? "***(已隐藏)" : "(空密码)") . "\n"; echo "========================================\n"; } private function printSuccess($result) { echo "✅ 数据库连接成功!\n"; echo "连接耗时: {$result['connection_time']}ms\n"; echo "MySQL服务器版本: {$result['server_version']}\n"; echo "MySQL客户端版本: {$result['client_version']}\n"; echo "----------------------------------------\n"; } private function printError($e) { echo "❌ 数据库连接失败!\n"; echo "错误代码: " . $e->getCode() . "\n"; echo "错误信息: " . $e->getMessage() . "\n"; $this->printTroubleshooting($e->getCode()); echo "========================================\n"; } private function printTroubleshooting($error_code) { echo "\n常见问题排查:\n"; $suggestions = [ 1045 => ["- 检查用户名和密码是否正确", "- 检查用户是否有远程访问权限"], 1049 => ["- 检查数据库名是否存在", "- 检查数据库名拼写是否正确"], 2002 => ["- 检查主机地址是否正确", "- 检查MySQL服务是否启动", "- 检查防火墙设置"], 2003 => ["- 检查端口是否正确", "- 检查MySQL服务是否启动", "- 检查防火墙设置"], 1044 => ["- 检查用户是否有访问该数据库的权限", "- 检查数据库权限设置"], 1698 => ["- 检查MySQL用户认证插件设置", "- 尝试使用mysql_native_password插件"], 1130 => ["- 检查MySQL用户的主机权限设置", "- 允许用户从当前主机连接"], 2013 => ["- 连接超时,检查网络状况", "- 检查MySQL服务器负载"] ]; if (isset($suggestions[$error_code])) { foreach ($suggestions[$error_code] as $suggestion) { echo "$suggestion\n"; } } else { echo "- 检查网络连接\n"; echo "- 检查MySQL服务状态\n"; echo "- 检查防火墙和网络安全组设置\n"; echo "- 检查密码中的特殊字符是否正确转义\n"; } } private function printFooter() { echo "========================================\n"; echo "所有测试完成!数据库连接正常。\n"; echo "========================================\n"; } } // 更安全的命令行参数处理 function parseCommandLineArgs() { global $argv; $options = [ 'host' => 'localhost', 'username' => 'root', 'password' => '', 'database' => 'test', 'port' => 3306 ]; // 手动解析参数,避免getopt对特殊字符的处理问题 for ($i = 1; $i < count($argv); $i++) { $arg = $argv[$i]; // 处理长选项 --option=value if (strpos($arg, '--') === 0) { $parts = explode('=', $arg, 2); $key = substr($parts[0], 2); $value = $parts[1] ?? ''; switch ($key) { case 'host': $options['host'] = $value; break; case 'user': $options['username'] = $value; break; case 'password': $options['password'] = $value; break; case 'database': $options['database'] = $value; break; case 'port': $options['port'] = $value; break; case 'help': showHelp(); exit(0); } } // 处理短选项 -o value elseif (strpos($arg, '-') === 0) { $key = $arg[1]; $value = $argv[$i + 1] ?? ''; switch ($key) { case 'h': $options['host'] = $value; $i++; break; case 'u': $options['username'] = $value; $i++; break; case 'p': $options['password'] = $value; $i++; break; case 'd': $options['database'] = $value; $i++; break; case 'P': $options['port'] = $value; $i++; break; } } } return $options; } // 交互式输入函数(用于安全输入密码) function readPassword($prompt = "请输入密码: ") { if (PHP_OS_FAMILY === 'Windows') { echo $prompt; // Windows系统隐藏输入比较困难,直接显示 $password = trim(fgets(STDIN)); } else { // Linux/Mac系统可以使用stty隐藏输入 echo $prompt; system('stty -echo'); $password = trim(fgets(STDIN)); system('stty echo'); echo "\n"; } return $password; } function showHelp() { echo "MySQL数据库连接测试工具\n\n"; echo "使用方法:\n"; echo " php " . basename(__FILE__) . " [选项]\n\n"; echo "选项:\n"; echo " -h, --host 数据库主机 (默认: localhost)\n"; echo " -u, --user 数据库用户名 (默认: root)\n"; echo " -p, --password 数据库密码 (建议用引号包裹特殊密码)\n"; echo " -d, --database 数据库名 (默认: test)\n"; echo " -P, --port 端口号 (默认: 3306)\n"; echo " --help 显示此帮助信息\n\n"; echo "密码特殊字符处理:\n"; echo " 如果密码包含特殊字符,请使用单引号或双引号包裹:\n"; echo " 正确: php script.php -p 'my@pass#word!'\n"; echo " 正确: php script.php -p \"my@pass#word!\"\n"; echo " 错误: php script.php -p my@pass#word!\n\n"; echo "示例:\n"; echo " php " . basename(__FILE__) . " -h 192.168.1.100 -u myuser -p 'my@pass#word!' -d mydb\n"; echo " php " . basename(__FILE__) . " --host=mysql.example.com --user=admin --password='your@password#'\n"; } // 主程序 if (PHP_SAPI === 'cli') { // 命令行模式 $config = parseCommandLineArgs(); // 如果密码为空,尝试交互式输入 if (empty($config['password'])) { $config['password'] = readPassword(); } $tester = new MySQLConnectionTester($config); $success = $tester->testConnection(); exit($success ? 0 : 1); } else { // Web浏览器模式 echo "
";
$config = [
'host' => $_POST['host'] ?? $_GET['host'] ?? 'localhost',
'username' => $_POST['user'] ?? $_GET['user'] ?? 'root',
'password' => $_POST['password'] ?? $_GET['password'] ?? '',
'database' => $_POST['database'] ?? $_GET['database'] ?? 'test',
'port' => $_POST['port'] ?? $_GET['port'] ?? 3306
];
$tester = new MySQLConnectionTester($config);
$tester->testConnection();
echo "";
}
?>