81 lines
2.2 KiB
TypeScript
81 lines
2.2 KiB
TypeScript
// src/lib/container-ops.ts — 容器操作(通过 SSH 执行 Docker 命令)
|
|
import { execFileSync } from 'child_process'
|
|
|
|
export type ContainerAction = 'restart' | 'stop' | 'start' | 'logs'
|
|
|
|
export interface ContainerOpResult {
|
|
success: boolean
|
|
action: ContainerAction
|
|
containerName: string
|
|
output?: string
|
|
error?: string
|
|
}
|
|
|
|
// 通过 SSH 在 txjp 服务器上执行 Docker 命令
|
|
function sshExec(cmd: string, timeoutMs = 15000): { stdout: string; stderr: string } {
|
|
try {
|
|
const result = execFileSync('ssh', ['txjp', cmd], {
|
|
encoding: 'utf-8',
|
|
timeout: timeoutMs,
|
|
maxBuffer: 1024 * 1024,
|
|
})
|
|
return { stdout: result.trim(), stderr: '' }
|
|
} catch (err: unknown) {
|
|
const e = err as { stderr?: Buffer; stdout?: Buffer; status?: number }
|
|
return {
|
|
stdout: e.stdout?.toString()?.trim() || '',
|
|
stderr: e.stderr?.toString()?.trim() || String(err),
|
|
}
|
|
}
|
|
}
|
|
|
|
// 执行容器操作
|
|
export async function containerOp(
|
|
containerName: string,
|
|
action: ContainerAction,
|
|
lines?: number,
|
|
): Promise<ContainerOpResult> {
|
|
if (!containerName) {
|
|
return { success: false, action, containerName: '', error: '容器名不能为空' }
|
|
}
|
|
|
|
let cmd: string
|
|
switch (action) {
|
|
case 'restart':
|
|
cmd = `docker restart ${containerName}`
|
|
break
|
|
case 'stop':
|
|
cmd = `docker stop ${containerName}`
|
|
break
|
|
case 'start':
|
|
cmd = `docker start ${containerName}`
|
|
break
|
|
case 'logs':
|
|
const n = Math.min(lines || 50, 200)
|
|
cmd = `docker logs --tail ${n} ${containerName}`
|
|
break
|
|
default:
|
|
return { success: false, action, containerName, error: '未知操作' }
|
|
}
|
|
|
|
try {
|
|
const { stdout, stderr } = sshExec(cmd)
|
|
if (stderr && !stdout) {
|
|
return { success: false, action, containerName, error: stderr }
|
|
}
|
|
return { success: true, action, containerName, output: stdout || 'OK' }
|
|
} catch (err) {
|
|
return { success: false, action, containerName, error: String(err) }
|
|
}
|
|
}
|
|
|
|
// 获取容器状态
|
|
export function getContainerStatus(containerName: string): string | null {
|
|
try {
|
|
const { stdout } = sshExec(`docker ps --format '{{.Status}}' -f name=^${containerName}$`)
|
|
return stdout || null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|