title: stdout and stderror from fabric task wrapped in celery
body: <p>im running a simple task, triggered from a django view:</p>
  
  <pre><code>task = mock_deploy.delay()
  </code></pre>
  
  <p>mock_deploy is defined as:</p>
  
  <pre><code>from celery.decorators import task as ctask
  from project.fabscripts.task.mock import *
  
  @ctask(name="mock_deploy")
  def mock_deploy():
      print "hi form celery task b4 mockdeploy 1234"
      output = execute(mock_deploy2)
      return "out: %s" % (output)
  </code></pre>
  
  <p>And the fabric task itself is defined as:</p>
  
  <pre><code>@task
  def mock_deploy2():
      lrun("ls -l /")
      lrun("ifconfig eth0")
      # i need to get the full output from those commands and save them to db
  </code></pre>
  
  <p>And now... I was trying to substitute stdout, overwriting fabric execute function:</p>
  
  <pre><code>def execute(task):
      output = StringIO()
      error = StringIO()
      sys.stdout = output
      sys.stderr = error
      task()
      sys.stdout = sys.__stdout__
      sys.stderr = sys.__stderr__
      return (output.getvalue(), error.getvalue())
  </code></pre>
  
  <p>And I was trying to substitute stdout within fabric task. No matter what i did, the only output i was getting was a first line of "what fabric wants to do"</p>
  
  <pre><code>out: [localhost] local: ls -l / 
  </code></pre>
  
  <p>Then, the whole output of the ls command was printed perfectly fine in celery log. Except for the missing one line of out: [localhost] local: ls -l / `9the one i managed to get as output)</p>
  
  <pre><code>[2012-06-14 21:33:56,587: DEBUG/MainProcess] TaskPool: Apply &lt;function execute_and_trace at 0x36710c8&gt; (args:('mock_deploy', '2a90d920-130a-4942-829b-87f4d5ebe80f', [], {}) kwargs:{'hostname': 's16079364', 'request': {'retries': 0, 'task': 'mock_deploy', 'utc': False, 'loglevel': 10, 'delivery_info': {'routing_key': u'celery', 'exchange': u'celery'}, 'args': [], 'expires': None, 'is_eager': False, 'eta': None, 'hostname': 's16079364', 'kwargs': {}, 'logfile': None, 'id': '2a90d920-130a-4942-829b-87f4d5ebe80f'}})
  [2012-06-14 21:33:56,591: DEBUG/MainProcess] Task accepted: mock_deploy[2a90d920-130a-4942-829b-87f4d5ebe80f] pid:22214
  hi form celery task b4 mockdeploy 1234
  total 3231728
  -rw-r--r--   1 root root 3305551148 2012-06-13 14:43 dumpling.sql
  drwxr-xr-x   2 root root       4096 2012-05-09 17:42 bin
  drwxr-xr-x   4 root root       4096 2012-02-14 15:21 boot
  drwxr-xr-x   2 root root       4096 2012-03-09 14:10 build
  drwxr-xr-x   2 root root       4096 2010-05-11 19:58 cdrom
  -rw-------   1 root root    2174976 2012-05-23 11:23 core
  drwxr-xr-x  15 root root       4080 2012-06-11 12:55 dev
  drwxr-xr-x 135 root root      12288 2012-06-14 21:15 etc
  drwxr-xr-x   6 root root         77 2012-05-21 14:41 home
  
  ...
  </code></pre>
  
  <p>A horrible horrible workaround is wrapping up a fabric run command to add a "> /tmp/logfile.log" on each command, then when the task is finished ill retrieve the file with scp...</p>
  
  <p>My question in short is how do i get the full output of a fabric task when its triggered with celery?</p>
  
  <p>The following did the trick:</p>
  
  <pre><code>@ctask(name="mock_deploy")
  def mock_deploy():
      env.roledefs.update({'remote':  ['root@1.1.1.1',]})
      output = StringIO()
      sys.stdout = output
      execute(mock_deploy2)
      sys.stdout = sys.__stdout__
      return output.getvalue()
  </code></pre>