@@ -144,7 +144,7 @@ def diff(self):
144
144
145
145
def exec_run (self , cmd , stdout = True , stderr = True , stdin = False , tty = False ,
146
146
privileged = False , user = '' , detach = False , stream = False ,
147
- socket = False , environment = None , workdir = None ):
147
+ socket = False , environment = None , workdir = None , demux = False ):
148
148
"""
149
149
Run a command inside this container. Similar to
150
150
``docker exec``.
@@ -166,6 +166,7 @@ def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
166
166
the following format ``["PASSWORD=xxx"]`` or
167
167
``{"PASSWORD": "xxx"}``.
168
168
workdir (str): Path to working directory for this exec session
169
+ demux (bool): Return stdout and stderr separately
169
170
170
171
Returns:
171
172
(ExecResult): A tuple of (exit_code, output)
@@ -180,14 +181,79 @@ def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
180
181
Raises:
181
182
:py:class:`docker.errors.APIError`
182
183
If the server returns an error.
184
+
185
+ Example:
186
+
187
+ Create a container that runs in the background
188
+
189
+ >>> client = docker.from_env()
190
+ >>> container = client.containers.run(
191
+ ... 'bfirsh/reticulate-splines', detach=True)
192
+
193
+ Prepare the command we are going to use. It prints "hello stdout"
194
+ in `stdout`, followed by "hello stderr" in `stderr`:
195
+
196
+ >>> cmd = '/bin/sh -c "echo hello stdout ; echo hello stderr >&2"'
197
+
198
+ We'll run this command with all four the combinations of ``stream``
199
+ and ``demux``.
200
+
201
+ With ``stream=False`` and ``demux=False``, the output is a string
202
+ that contains both the `stdout` and the `stderr` output:
203
+
204
+ >>> res = container.exec_run(cmd, stream=False, demux=False)
205
+ >>> res.output
206
+ b'hello stderr\n hello stdout\n '
207
+
208
+ With ``stream=True``, and ``demux=False``, the output is a
209
+ generator that yields strings containing the output of both
210
+ `stdout` and `stderr`:
211
+
212
+ >>> res = container.exec_run(cmd, stream=True, demux=False)
213
+ >>> next(res.output)
214
+ b'hello stdout\n '
215
+ >>> next(res.output)
216
+ b'hello stderr\n '
217
+ >>> next(res.output)
218
+ Traceback (most recent call last):
219
+ File "<stdin>", line 1, in <module>
220
+ StopIteration
221
+
222
+ With ``stream=True`` and ``demux=True``, the generator now
223
+ separates the streams, and yield tuples
224
+ ``(stdout, stderr)``:
225
+
226
+ >>> res = container.exec_run(cmd, stream=True, demux=True)
227
+ >>> next(res.output)
228
+ (b'hello stdout\n ', None)
229
+ >>> next(res.output)
230
+ (None, b'hello stderr\n ')
231
+ >>> next(res.output)
232
+ Traceback (most recent call last):
233
+ File "<stdin>", line 1, in <module>
234
+ StopIteration
235
+
236
+ Finally, with ``stream=False`` and ``demux=True``, the whole output
237
+ is returned, but the streams are still separated:
238
+
239
+ >>> res = container.exec_run(cmd, stream=True, demux=True)
240
+ >>> next(res.output)
241
+ (b'hello stdout\n ', None)
242
+ >>> next(res.output)
243
+ (None, b'hello stderr\n ')
244
+ >>> next(res.output)
245
+ Traceback (most recent call last):
246
+ File "<stdin>", line 1, in <module>
247
+ StopIteration
183
248
"""
184
249
resp = self .client .api .exec_create (
185
250
self .id , cmd , stdout = stdout , stderr = stderr , stdin = stdin , tty = tty ,
186
251
privileged = privileged , user = user , environment = environment ,
187
252
workdir = workdir
188
253
)
189
254
exec_output = self .client .api .exec_start (
190
- resp ['Id' ], detach = detach , tty = tty , stream = stream , socket = socket
255
+ resp ['Id' ], detach = detach , tty = tty , stream = stream , socket = socket ,
256
+ demux = demux
191
257
)
192
258
if socket or stream :
193
259
return ExecResult (None , exec_output )
0 commit comments