From 612e36e4ea8b5061e94aacd9e0cab03e9a73e0aa Mon Sep 17 00:00:00 2001 From: fly6516 Date: Fri, 3 Jan 2025 03:01:39 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E5=A4=9A=E8=AF=AD=E8=A8=80=E7=BC=96=E8=AF=91=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/multiFileRunner.ts | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/actions/multiFileRunner.ts diff --git a/src/actions/multiFileRunner.ts b/src/actions/multiFileRunner.ts new file mode 100644 index 0000000..5e317cd --- /dev/null +++ b/src/actions/multiFileRunner.ts @@ -0,0 +1,84 @@ +import Docker from 'dockerode'; +import fs from 'fs'; +import path from 'path'; + +// 创建 Docker 客户端实例 +const docker = new Docker(); + +/** + * 执行多文件代码的函数 + * @param params 包含文件列表和语言的参数 + * @returns 执行结果或错误信息 + */ +export const runMultiFileCode = async (params: { files: { name: string; content: string }[]; language: string }) => { + const { files, language } = params; + + if (!files || files.length === 0 || !language) { + throw new Error('Files and language are required.'); + } + + // 支持的编程语言 + const supportedLanguages = ['c', 'java', 'python']; + if (!supportedLanguages.includes(language)) { + throw new Error(`Language '${language}' is not supported. Only 'c', 'java', and 'python' are supported.`); + } + + // 根据语言设置编译和运行命令 + const compileAndRunCmd = + language === 'c' + ? 'gcc *.c -o main && ./main' + : language === 'java' + ? 'javac *.java && java Main' + : 'python3 script.py'; + + // 创建临时目录存放代码文件 + const tempDir = path.join('/tmp', `${Date.now()}`); + fs.mkdirSync(tempDir, { recursive: true }); + + try { + // 将所有文件写入临时目录 + for (const file of files) { + const filePath = path.join(tempDir, file.name); + fs.writeFileSync(filePath, file.content); + } + + // 创建 Docker 容器 + const container = await docker.createContainer({ + Image: 'fly6516.synology.me:8080/multilang:latest', + Cmd: ['sh', '-c', compileAndRunCmd], + AttachStdout: true, + AttachStderr: true, + Tty: false, + HostConfig: { + Binds: [`${tempDir}:/workspace`], // 挂载临时目录到容器 + }, + WorkingDir: '/workspace', + }); + + await container.start(); + + // 获取容器日志 + const logs = await container.logs({ stdout: true, stderr: true, follow: true }); + + let output = ''; + logs.on('data', (data: Buffer) => { + output += data.toString().replace(/[\x00-\x1F\x7F]/g, ''); // 去除不可见字符 + }); + + const exitCode = await container.wait(); // 等待容器执行结束 + await container.remove(); // 移除容器 + + // 返回执行结果或错误信息 + if (exitCode.StatusCode === 0) { + return { output }; + } else { + return { error: `Execution failed with exit code ${exitCode.StatusCode}. Output: ${output}` }; + } + } catch (error) { + // 捕获异常并返回详细错误信息 + return { error: `An error occurred: ${(error as Error).message}` }; + } finally { + // 清理临时目录 + fs.rmSync(tempDir, { recursive: true, force: true }); + } +};