fix: agent install.sh 404 + 三阶段构建编译agent二进制

问题: 构建上下文 ./backend 无法访问 ../agent, 导致容器内
/app/agent/deploy/install.sh 不存在, 返回 404

修复:
- Dockerfile 改为三阶段构建 (backend go1.21 + agent go1.24 交叉编译 + alpine runtime)
- docker-compose backend build context 改为项目根
- routes.go /agent/arch 安装命令改为动态获取 URL
- 新增 .dockerignore
- agent_install.go: SSH 远程安装 handler
- AgentWizard.tsx: 复制按钮 fallback + 动态 server URL
- ServerTableRow.tsx: agent 状态判断

验证: curl|bash 安装成功, agent 上报数据到 MySQL ✅
This commit is contained in:
Logan committed 2026-06-18 09:44:12 +08:00
1 parent d0344c2f52
commit d0b94d39c0
9 files changed
+281 -38

No files matched your search

+21 -5
View File
@@ -17,11 +17,12 @@ interface AgentWizardProps {
onOpenChange: (open: boolean) => void;
}
/** 自动检测服务器地址:使用当前浏览器访问的主机名,端口固定 8080 */
/** 自动检测服务器地址:使用当前浏览器访问的地址(协议+主机+端口) */
function detectServerAddress(): string {
if (typeof window !== 'undefined' && window.location) {
const host = window.location.hostname;
return host ? `http://${host}:8080` : 'http://127.0.0.1:8080';
// 直接用当前浏览器的 origin(如 http://10.10.10.150),
// Nginx 会将 /agent/ 请求代理到后端
return window.location.origin;
}
return 'http://127.0.0.1:8080';
}
@@ -35,12 +36,27 @@ export function AgentWizard({ open, onOpenChange }: AgentWizardProps) {
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(installCommand);
// 优先使用现代 Clipboard API(需要 HTTPS 或 localhost)
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(installCommand);
} else {
// 降级方案:用隐藏 textarea + execCommand('copy'),兼容 HTTP 环境
const textarea = document.createElement('textarea');
textarea.value = installCommand;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
textarea.style.pointerEvents = 'none';
document.body.appendChild(textarea);
textarea.select();
const ok = document.execCommand('copy');
document.body.removeChild(textarea);
if (!ok) throw new Error('execCommand failed');
}
setCopied(true);
toast.success('安装命令已复制');
setTimeout(() => setCopied(false), 2000);
} catch {
toast.error('复制失败,请手动复制');
toast.error('复制失败,请手动选中复制');
}
};
@@ -12,7 +12,7 @@ import {
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { TableCell, TableRow } from '@/components/ui/table';
import { Edit, MoreHorizontal, Server as ServerIcon, Terminal, Trash2 } from 'lucide-react';
import { Edit, MoreHorizontal, Server as ServerIcon, Terminal, Trash2, Download } from 'lucide-react';
import { getStatusBadge, getTags, getUsageColor } from './serverHelpers';
interface ServerTableRowProps {
+4
View File
@@ -143,6 +143,10 @@ export const serverApi = {
// 后端暂无单机 metrics,用 dashboard metrics
return http.get('/dashboard/metrics');
},
// 远程安装 Agent(通过 SSH 执行安装脚本)
installAgent: async (id: number | string, token: string) => {
return http.post<{ installed: boolean; arch: string; output: string }>(`/servers/${id}/install-agent?token=${encodeURIComponent(token)}`);
},
};
// ==================== K8s 集群 API ====================