11import os .path
22import pty
33import select
4+ import subprocess
45import sys
56import termios
67import tty
@@ -179,16 +180,21 @@ def remove_volume(self, volume_name: str):
179180 if volume .name == volume_name :
180181 volume .remove (True )
181182
182- def exec_docker_subprocess (self , container : Container , command : Command = None , attributes : List = None ) -> int :
183- old_tty = termios .tcgetattr (sys .stdin )
184- tty .setraw (sys .stdin .fileno ())
183+ def exec_docker_subprocess (self , container , command : Command = None , attributes : List = None ) -> int :
184+ try :
185+ old_tty = termios .tcgetattr (sys .stdin )
186+ tty .setraw (sys .stdin .fileno ())
187+ return self .exec_docker_subprocess_tty (old_tty , container , command , attributes )
188+ except termios .error :
189+ return self .exec_docker_subprocess_stdout_pipe (container , command , attributes )
185190
186- # open pseudo-terminal to interact with subprocess
187- master_fd , slave_fd = pty .openpty ()
191+ def exec_docker_subprocess_tty (self , old_tty , container , command : Command = None , attributes : List = None ):
188192 try :
193+ # open pseudo-terminal to interact with subprocess
194+ master_fd , slave_fd = pty .openpty ()
189195 # use os.setsid() make it run in a new process group, or bash job control will not be enabled
190196 p = Popen (
191- self .build_command (container , command , attributes ),
197+ self .build_command (container , command , attributes , _tty = True ),
192198 preexec_fn = os .setsid ,
193199 stdin = slave_fd ,
194200 stdout = slave_fd ,
@@ -197,7 +203,7 @@ def exec_docker_subprocess(self, container: Container, command: Command = None,
197203 )
198204
199205 while p .poll () is None :
200- r , w , e = select .select ([sys .stdin , master_fd ], [], [], 0.5 )
206+ r , w , e = select .select ([sys .stdin , master_fd ], [], [], 0.2 )
201207 if sys .stdin in r :
202208 d = os .read (sys .stdin .fileno (), 10240 )
203209 os .write (master_fd , d )
@@ -210,7 +216,28 @@ def exec_docker_subprocess(self, container: Container, command: Command = None,
210216 termios .tcsetattr (sys .stdin , termios .TCSADRAIN , old_tty )
211217 return p .poll ()
212218
213- def build_command (self , container : Container , command : Command = None , attributes : List = None ) -> List [str ]:
219+ def exec_docker_subprocess_stdout_pipe (self , container , command : Command = None , attributes : List = None ):
220+ process = subprocess .Popen (
221+ self .build_command (container , command , attributes , _tty = False ),
222+ preexec_fn = os .setsid ,
223+ stdout = subprocess .PIPE ,
224+ universal_newlines = True
225+ )
226+ while True :
227+ output = process .stdout .readline ()
228+ if output == '' and process .poll () is not None :
229+ break
230+ if output :
231+ print (output .strip ())
232+ return process .poll ()
233+
234+ def build_command (
235+ self ,
236+ container : Container ,
237+ command : Command = None ,
238+ attributes : List = None ,
239+ _tty : bool = True
240+ ) -> List [str ]:
214241 if attributes is None :
215242 attributes = []
216243
@@ -223,11 +250,12 @@ def build_command(self, container: Container, command: Command = None, attribute
223250 cmd_base = [
224251 'docker' ,
225252 'run' ,
226- '-it' ,
227253 '--pid=host' ,
228254 '--rm' ,
229255 '--name=' + self .get_container_name (container ),
230256 ]
257+ if _tty :
258+ cmd_base = cmd_base + ['-it' ]
231259 cmd_base = cmd_base + self .build_docker_run_arguments (container )
232260 return cmd_base + [
233261 container .image ,
0 commit comments