AgentDepthAgent 工程学习指南
输入概念或问题,检索正文和待编写目录。
第一次学习?从 L0 总览开始 →

沙箱、资源配额与网络隔离

我的学习 →

正在读取学习记录…

Agent 运行一段统计任务时,需要避免任务拖住主服务。正常任务将 2、3、5 相加,返回 10;超过允许时间的任务则结束,并让主服务继续处理下一次请求。

进程是操作系统运行程序的单位,有自己的内存空间和退出状态。沙箱是在受控边界中运行任务,限制它能读取哪些文件、使用哪些系统能力和连接哪些网络。把任务放进子进程,能管理生命周期;文件、账户和网络权限还要由操作系统或隔离运行平台施加。

资源配额是给任务设定 CPU、内存、进程数或时间上限。时间超限与内存超限是不同问题:等五秒的任务可能不消耗多少 CPU,快速分配内存的任务却可能立即影响主机。

子进程、容器和配额分别解决什么

主程序用 subprocess.run 启动另一个 Python 进程,等待结果并设置超时。执行命令是参数列表,没有经过 shell 字符串解释;任务名映射到固定良性代码。独立临时目录给每次任务单独的工作位置,退出时清理。

-I 是 Python 的隔离启动选项,主要影响 Python 导入路径和 Python 环境变量处理;它并不撤销操作系统授予进程的文件或网络权限。传给子进程的环境变量由显式白名单构建,避免把应用环境里的秘密直接继承过去。程序没有加入任何网络调用,但操作系统仍可能允许该子进程联网。

容器常通过 namespace 提供进程、挂载和网络等视图隔离,通过 cgroup 控制资源。容器里的进程通常仍共享宿主内核,需要减少 capability(内核授予的特殊操作能力)、限制系统调用、使用非特权账户、避免挂载敏感宿主目录。更强的任务边界可能使用独立虚拟机;它也要管理凭据和网络出口。

层次控制目标示例实际发生的行为
子进程启动、等待、超时结束固定任务有独立进程
工作目录工作文件位置与清理创建并清理独立临时目录
CPU / 内存 / 进程配额防止资源耗尽需操作系统或容器运行器配置
文件权限 / 网络出口限制可访问资源需账户、挂载与网络策略
Python 导入隔离降低路径和环境干扰子进程使用 -I
沙箱、资源配额与网络隔离中输入、检查和结果分支的关系
图1:固定任务进入独立子进程;计算正常返回10,等待超过0.3秒时终止子进程,主程序继续处理下一项。

在空目录保存并运行两个文件

在 PowerShell 输入以下命令创建练习目录,并进入目录。目录创建好后,在编辑器中新建下面两份文件并保存到这个目录。

PowerShell
New-Item -ItemType Directory -Force l8-sandbox
Set-Location l8-sandbox

macOS 终端:

Bash
mkdir -p l8-sandbox
cd l8-sandbox

先保存 sandbox_demo.py。它只接受固定任务名,子进程执行的两段代码都已经写在文件里。

Python
"""运行预先写好的良性子进程,观察超时与临时目录。"""
import os
from pathlib import Path
import subprocess
import sys
import tempfile

TIMEOUT = 0.3
# 任务名映射到固定代码;不接收用户提供的 Python 代码。
WORKERS = {
    "sum": "print(sum([2, 3, 5]))",
    "wait": "import time; time.sleep(5); print('done')",
}

def run_worker(task, timeout):
    if task not in WORKERS:
        return "拒绝:未知任务"
    if timeout <= 0:
        raise ValueError("超时必须大于零")
    # 临时目录使用系统配置的位置,结束后自动清理。
    with tempfile.TemporaryDirectory() as workdir:
        # 不继承应用秘密;Windows 系统目录变量用于解释器启动。
        env = {"PYTHONIOENCODING": "utf-8"}
        if "SystemRoot" in os.environ:
            env["SystemRoot"] = os.environ["SystemRoot"]
        try:
            result = subprocess.run(
                [sys.executable, "-I", "-c", WORKERS[task]],
                cwd=workdir, env=env, capture_output=True,
                text=True, encoding="utf-8", timeout=timeout, check=False,
            )
        except subprocess.TimeoutExpired:
            return "超时:子进程已结束"
        if result.returncode:
            return "失败:退出码=" + str(result.returncode)
        return "完成:" + result.stdout.strip()

def main():
    print("固定计算 ->", run_worker("sum", 3))
    print("等待任务 ->", run_worker("wait", TIMEOUT))
    print("未知任务 ->", run_worker("unknown", 3))

if __name__ == "__main__":
    main()

再保存 test_sandbox.py。测试通过程序的公开函数检查正常路径与拒绝路径;测试文件和主程序放在同一目录,才能按文件名导入。

Python
import unittest
# 固定良性输入检查正常、拒绝和边界路径,不连接外部服务。
from sandbox_demo import run_worker

class ProcessTests(unittest.TestCase):
    def test_fixed_computation(self):
        self.assertEqual(run_worker("sum", 3), "完成:10")

    def test_timeout(self):
        self.assertEqual(run_worker("wait", 0.3), "超时:子进程已结束")

    def test_unknown_task(self):
        self.assertEqual(run_worker("unknown", 3), "拒绝:未知任务")

    def test_invalid_timeout(self):
        with self.assertRaises(ValueError):
            run_worker("sum", 0)

    def test_repeat_after_timeout(self):
        run_worker("wait", 0.3)
        self.assertEqual(run_worker("sum", 3), "完成:10")

if __name__ == "__main__":
    unittest.main()

返回同一个终端,先列出当前目录内容,确认两个文件名都以 .py 结尾,然后运行主程序。

Bash
ls
python -X utf8 sandbox_demo.py

程序输出:

TXT
固定计算 -> 完成:10
等待任务 -> 超时:子进程已结束
未知任务 -> 拒绝:未知任务

固定计算返回 10。等待任务需要五秒,而 TIMEOUT 为 0.3 秒,所以父进程结束它并返回超时。未知任务在启动前被拒绝。这里管理的是固定单个子进程:任意代码若生成后代进程,需要进程组、Windows Job Object 或容器生命周期管理来回收整个任务树;否则只结束直接子进程会留下后代。

capture_output 把输出收集到父进程内存;这份固定任务输出极小。运行任意任务时还需用限量流式读取处理输出,配合内存和 CPU 配额,才能控制大量输出和资源占用。临时工作目录也不自动阻止绝对路径访问。

运行测试:

Bash
python -X utf8 -m unittest -v test_sandbox.py

末尾应显示 Ran 5 tests 和 OK。若提示找不到模块,先用 dir 核对目录与文件名。

改一处,观察决定怎样变化

把 TIMEOUT = 0.3 改成 TIMEOUT = 6,重新运行主程序,约五秒后第二行变为 等待任务 -> 完成:done。同一任务在较大的等待时间内完成;计算任务仍然返回 10。再将常量恢复为 0.3。

Bash
python -X utf8 sandbox_demo.py

恢复原值后,重新运行测试。

为代码执行工具选择实际隔离设施

在 Windows 上,任务账户的文件 ACL 决定能读写哪些路径,Job Object 可管理进程树和资源限制,防火墙或受控代理管理网络出口。在 Linux 容器上,可从非 root 用户、只读根文件系统、受控挂载、CPU/内存/进程数上限和禁用网络的任务配置开始,再按需求开放权限。配置的落实情况需要在部署平台逐项测试。

症状检查位置修正方向
计算任务也超时正常分支的超时与机器负载保留启动余量;示例正常分支使用三秒
超时后仍有后代任务任务树回收机制绑定 Job Object、进程组或容器任务生命周期
程序能读工作目录外的文件账户权限与挂载限制文件权限,核对敏感路径未挂入
程序能外连网络策略在系统层关闭网络或只开放受控出口
主服务内存上涨输出缓存与内存配额流式限量收集,配置内存上限

Python subprocess 文档说明超时和进程管理行为;Docker 安全文档解释 namespace、资源控制和守护进程权限。

课后练习展开习题收起习题

4 道练习 · 客观题规则评分 · 其余题目待批改

正在读取本地记录…

不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。

练习 1 / 4 · v1.0.1

选择题 · 先判断边界

关于“沙箱、资源配额与网络隔离”,哪种做法更稳妥?

对应知识点:L8-sandbox

选择一个答案
练习 2 / 4 · v1.0.0

简答题 · 解释失败

写出一个失败输入并说明记录字段。

对应知识点:L8-sandbox

练习 3 / 4 · v1.0.0

代码题 · 边界测试

补充正常、边界、失败三组输入和预期结果。

对应知识点:L8-sandbox

练习 4 / 4 · v1.0.0

场景题 · 结果未知

证据不足时如何设计状态和人工接管?

对应知识点:L8-sandbox

图片查看器
100%

文章配图 · 按 Esc 关闭