> ## Documentation Index
> Fetch the complete documentation index at: https://ppio.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 导出代码执行日志

> 将沙箱中运行代码的日志重定向到文件，并下载到本地进行调试和分析。

## 概述

在 PPIO Agent 沙箱中执行代码后，通常需要获取运行日志进行调试和分析。本文档介绍如何将代码的日志重定向到文件，并从沙箱下载到客户端（本地）。详细文件系统操作可参考 [下载文件](/sandbox/filesystem-download)。

涵盖两种场景：

1. **代码本身没有日志配置** — 通过 stdout/stderr 重定向捕获日志
2. **代码本身已有日志配置**（如 Python logging 输出到文件） — 直接下载已有的日志文件

## 场景一：代码无日志配置，通过重定向捕获日志

### 方案 A：使用 `commands.run()` + Shell 重定向

通过 Shell 的 `>` / `2>&1` 将 stdout 和 stderr 重定向到沙箱内的日志文件，然后下载。

<CodeGroup>
  ```python Python theme={null}
  import os
  from ppio_sandbox.code_interpreter import Sandbox

  os.environ["PPIO_API_KEY"] = "YOUR API KEY"

  sandbox = Sandbox.create()

  # 定义沙箱内的日志文件路径
  log_file = "/tmp/app.log"

  code = """
  import sys

  print('这是标准输出日志')
  print('处理中...', file=sys.stderr)
  print('执行完成')
  """

  # 上传代码到沙箱
  sandbox.files.write("/home/user/test.py", code)

  # 执行代码，将 stdout 和 stderr 都重定向到日志文件
  # 使用 2>&1 将 stderr 合并到 stdout，再通过 > 重定向到文件
  try:
      result = sandbox.commands.run(f'python3 /home/user/test.py > {log_file} 2>&1')
  except Exception as e:
      print(e)

  # 从沙箱读取日志文件
  log_content = sandbox.files.read(log_file)

  # 保存到本地
  with open('./app.log', 'w') as f:
      f.write(log_content)

  print("日志已下载到 ./app.log")

  sandbox.kill()
  ```
</CodeGroup>

### 方案 B：使用 `run_code()` 捕获执行结果中的日志

`run_code()` 返回的执行结果中自带 `logs`，可以直接写入文件，无需额外的 Shell 重定向。

<CodeGroup>
  ```python Python theme={null}
  import os
  from ppio_sandbox.code_interpreter import Sandbox

  os.environ["PPIO_API_KEY"] = "YOUR API KEY"

  sandbox = Sandbox.create()

  # 执行 Python 代码
  execution = sandbox.run_code("""
  import sys

  print("这是标准输出日志")
  print("处理中...", file=sys.stderr)
  print("执行完成")
  """)

  # execution.logs 包含了 stdout 的输出
  log_content = str(execution.logs)

  # 保存到本地
  with open('./app.log', 'w') as f:
      f.write(log_content)

  print("日志已保存到 ./app.log")

  sandbox.kill()
  ```
</CodeGroup>

## 场景二：代码已有日志配置，日志输出到指定目录

很多项目代码中已经配置了日志框架（如 Python 的 `logging` 模块），日志会输出到指定的文件路径。此时只需要知道日志文件的位置，直接从沙箱下载即可。

<CodeGroup>
  ```python Python theme={null}
  import os
  from ppio_sandbox.code_interpreter import Sandbox

  os.environ["PPIO_API_KEY"] = "YOUR API KEY"

  sandbox = Sandbox.create()
  print(f"Sandbox created: {sandbox.sandbox_id}")

  # 步骤 1：上传应用代码到沙箱
  app_code = """\
  import logging
  import sys

  logging.basicConfig(
      filename='/home/user/logs/app.log',
      level=logging.DEBUG,
      format='%(asctime)s [%(levelname)s] %(message)s',
  )

  logger = logging.getLogger(__name__)

  logger.info('Application started')
  logger.debug('Loading configuration...')
  logger.warning('Memory usage is high')
  logger.error('Failed to connect to database')

  print('stdout: all tasks completed')
  print('stderr: a warning message', file=sys.stderr)
  """

  sandbox.commands.run("mkdir -p /home/user/logs")
  sandbox.files.write("/home/user/main.py", app_code)
  print("Code uploaded to /home/user/main.py")

  # 步骤 2：执行应用代码
  print("Running application...")
  result = sandbox.commands.run("cd /home/user && python3 main.py")
  print(f"stdout: {result.stdout}")
  print(f"stderr: {result.stderr}")

  # 步骤 3：下载日志文件
  log_content = sandbox.files.read("/home/user/logs/app.log")

  with open("./app.log", "w") as f:
      f.write(log_content)

  print(f"Log downloaded to ./app.log ({len(log_content)} bytes)")
  print("--- Log content ---")
  print(log_content)

  sandbox.kill()
  print("Sandbox destroyed")
  ```
</CodeGroup>

## 注意事项

1. **文件大小**：沙箱存储空间为 20 GB，注意日志文件不要太大。
2. **编码问题**：`sandbox.files.read()` 返回的是字符串，如果日志包含二进制内容，可能需要特殊处理。
3. **沙箱生命周期**：日志下载要在 `sandbox.kill()` 之前完成，沙箱销毁后文件不可恢复。
4. **并发写入**：如果代码有多进程/多线程写日志，建议各自写入不同文件，避免写入冲突。
