.. _guide-debugging: ====================================== 调试 ====================================== Debugging .. _tut-remote_debug: 远程调试任务(使用 pdb) ==================================== Debugging Tasks Remotely (using pdb) 基础知识 ------------ Basics .. tab:: 中文 :mod:`celery.contrib.rdb` 是 :mod:`pdb` 的一个扩展版本,支持对无法访问终端的进程进行远程调试。 使用示例: .. code-block:: python from celery import task from celery.contrib import rdb @task() def add(x, y): result = x + y rdb.set_trace() # <- 设置断点 return result :func:`~celery.contrib.rdb.set_trace` 会在当前位置设置一个断点, 并创建一个套接字(socket),你可以通过 telnet 连接该端口,从而远程调试你的任务。 调试器可能会被多个进程同时启动,因此不会使用固定端口,而是从一个基础端口(默认 6900)开始搜索可用端口。 可以通过设置环境变量 :envvar:`CELERY_RDB_PORT` 来更改基础端口。 默认情况下,调试器只允许本地主机访问; 如需从外部访问,需设置环境变量 :envvar:`CELERY_RDB_HOST`。 当 worker 执行到断点时,会记录如下日志信息: .. code-block:: text [INFO/MainProcess] Received task: tasks.add[d7261c71-4962-47e5-b342-2448bedd20e8] [WARNING/PoolWorker-1] Remote Debugger:6900: Please telnet 127.0.0.1 6900. Type `exit` in session to continue. [2011-01-18 14:25:44,119: WARNING/PoolWorker-1] Remote Debugger:6900: Waiting for client... 连接指定端口后,你将进入一个 `pdb` shell: .. code-block:: console $ telnet localhost 6900 Connected to localhost. Escape character is '^]'. > /opt/devel/demoapp/tasks.py(128)add() -> return result (Pdb) 输入 ``help`` 可以查看可用命令列表。 如果你之前没有使用过 `pdb`,建议阅读 `Python Debugger Manual`_。 以下是一个调试示例:读取变量 ``result`` 的值、修改它,并继续任务执行: .. code-block:: text (Pdb) result 4 (Pdb) result = 'hello from rdb' (Pdb) continue Connection closed by foreign host. 我们“破坏性”修改的结果可以在 worker 日志中看到: .. code-block:: text [2011-01-18 14:35:36,599: INFO/MainProcess] Task tasks.add[d7261c71-4962-47e5-b342-2448bedd20e8] succeeded in 61.481s: 'hello from rdb' .. tab:: 英文 :mod:`celery.contrib.rdb` is an extended version of :mod:`pdb` that enables remote debugging of processes that doesn't have terminal access. Example usage: .. code-block:: python from celery import task from celery.contrib import rdb @task() def add(x, y): result = x + y rdb.set_trace() # <- set break-point return result :func:`~celery.contrib.rdb.set_trace` sets a break-point at the current location and creates a socket you can telnet into to remotely debug your task. The debugger may be started by multiple processes at the same time, so rather than using a fixed port the debugger will search for an available port, starting from the base port (6900 by default). The base port can be changed using the environment variable :envvar:`CELERY_RDB_PORT`. By default the debugger will only be available from the local host, to enable access from the outside you have to set the environment variable :envvar:`CELERY_RDB_HOST`. When the worker encounters your break-point it'll log the following information: .. code-block:: text [INFO/MainProcess] Received task: tasks.add[d7261c71-4962-47e5-b342-2448bedd20e8] [WARNING/PoolWorker-1] Remote Debugger:6900: Please telnet 127.0.0.1 6900. Type `exit` in session to continue. [2011-01-18 14:25:44,119: WARNING/PoolWorker-1] Remote Debugger:6900: Waiting for client... If you telnet the port specified you'll be presented with a `pdb` shell: .. code-block:: console $ telnet localhost 6900 Connected to localhost. Escape character is '^]'. > /opt/devel/demoapp/tasks.py(128)add() -> return result (Pdb) Enter ``help`` to get a list of available commands, It may be a good idea to read the `Python Debugger Manual`_ if you have never used `pdb` before. To demonstrate, we'll read the value of the ``result`` variable, change it and continue execution of the task: .. code-block:: text (Pdb) result 4 (Pdb) result = 'hello from rdb' (Pdb) continue Connection closed by foreign host. The result of our vandalism can be seen in the worker logs: .. code-block:: text [2011-01-18 14:35:36,599: INFO/MainProcess] Task tasks.add[d7261c71-4962-47e5-b342-2448bedd20e8] succeeded in 61.481s: 'hello from rdb' .. _`Python Debugger Manual`: http://docs.python.org/library/pdb.html 技巧 ---- Tips .. _breakpoint_signal: 启用断点信号 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Enabling the break-point signal .. tab:: 中文 如果设置了环境变量 :envvar:`CELERY_RDBSIG`,则在接收到 `SIGUSR2` 信号时,worker 将自动打开一个 rdb 会话。 此行为适用于主进程和 worker 子进程。 例如以下方式启动 worker: .. code-block:: console $ CELERY_RDBSIG=1 celery worker -l INFO 随后你可以通过如下命令向任意一个 worker 进程发送信号以触发 rdb 会话: .. code-block:: console $ kill -USR2 <pid> .. tab:: 英文 If the environment variable :envvar:`CELERY_RDBSIG` is set, the worker will open up an rdb instance whenever the `SIGUSR2` signal is sent. This is the case for both main and worker processes. For example starting the worker with: .. code-block:: console $ CELERY_RDBSIG=1 celery worker -l INFO You can start an rdb session for any of the worker processes by executing: .. code-block:: console $ kill -USR2 <pid>