How to Implement a Web-based Terminal with Docker 2015-03-14
Who am I 杜万 (Vangie Du) Full-Stack Web Developer Linux fans Working on Coding@Shanghai
About Coding Project Management Source Code Management Code Insight Web Development Cloud Development Platform https://coding.net Quality Analysis
Contents What is a Terminal Process Groups, Sessions and Job Control Pseudoterminals and Terminal emulators Implements a Web-based Terminal Embedded in Docker Container
What is a Terminal
Go Back In Time typewriter ticker tape printer In 1869,the stock ticker was invented
Terminal A device that enables you to communicate with a computer. TeleTYpewriter, TTY Combination of keyboard and display screen. DEC VT100 terminal
Text Terminal Keyboard stdin Program stdout Display stderr
Process performing I/O characters read by process characters written by process Terminal driver Input queue If echoing enabled Output queue characters typed at terminal Terminal device characters displayed at terminal
Three Layers of Terminal Subsystem characters, signals Control-C, backspace, delete Character device interface read(),write(),ioctrl() Line discipline Hardware Driver LF CR/LF
Process Groups, Sessions and Job Control
Multiple Tasks program1 User Terminal input output program2 suspended at need for write to terminal kill suspend program3 endless loop
Session Process Group Process Process Group Process Process
PID process identifier PGID process group identifier == the PID of process group leader SID seesion identifier == the PID of session leader
Exec Command in Bash $ echo $$ 400 $ find / 2>/dev/null wc -l & [1] 659 $ sort < longlist uniq -c #Display the PID of the Bash #Creates 2 processes in background group #Creates 2 processes in foreground group
Session 400 session leader process group leaders bash PID = 400 PPID = 399 PGID = 400 SID = 400 find PID = 658 PPID = 400 PGID = 658 SID = 400 sort PID = 660 PPID = 400 PGID = 660 SID = 400 controlling process process group 400 background process group controlling terminal foreground PGID = 660 background SID = 400 wc uniq PID = 659 PID = 661 PPID = 400 PPID = 400 PGID = 658 PGID = 600 SID = 400 SID = 400 process group 658 process group 660 foreground process group PROCESSES IN MEMORY
Job Control Running in foreground 1. Control-C (SIGINT) 2. Control-\ (SIGOUT) Terminated $ command fg (SIGCOUT) kill $ command & fg Control-Z (SIGTSTP) kill Running in background bg (SIGCONT) 1. kill -STOP (SIGSTOP) 2. Terminal Read (SIGTTIN) 3. Terminal Write (+TOSTOP) (SIGTTOU) Stopped in background
Pseudoterminals and Terminal emulators
What is Terminal Emulator A terminal emulator is a a computer application that emulates or behaves like a hardware terminal composed of at least a keyboard and monitor.
Software Hardware kernel Terminal Physical line UART UART driver Line discipline TTY driver User process User process User process
Software Hardware kernel Display Keyboard VGA driver Keyboard driver Terminal emulator Line discipline TTY driver User process User process User process
Software kernel Line discipline PTY master PTY slave Terminal emulator User process User process User process
How to Operate a Terminaloriented Program over a Network? client program terminal-oriented program stdin stdout, stderr socket user space socket? Terminal TCP/IP kernel space TCP/IP User at Terminal Network
Two Programs Communicating via a Pseudoterminal user space kernel space driver program pty master fork(), exec() terminal-oriented program stdin pty slave stdout, stderr is the controlling terminal for
How SSH Uses a PseudoTerminal ssh client ssh server login shell stdin stdout, stderr socket user space socket stdin stdout, stderr Terminal TCP/IP kernel space TCP/IP pty master pty slave User at Terminal Network
Implements a Web-based Terminal
User at Browser Web Terminal Terminal emulator websocket server bash user space stdin stdout, stderr websocket client websocket stdin stdout, stderr websocket TCP/IP kernel space TCP/IP pty master pty slave Network
Initialize a Project of Nodejs $ mkdir docker-web-terminal && cd $_ $ npm init && bower init $ git init && git add. && git commit -m first commit $ git remote add origin git@coding.net:duwan/docker-webterminal.git $ git push -u origin master
Install Dependencies Package $ npm install --save coffee-script \ express \ pty.js \ socket.io $ bower install --save jquery \ socket.io-client \ CodeboxIDE/sh.js \ coffeescript
Backend Source 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [pty, sio, express, http] = (require lib for lib in ['pty.js', 'socket.io', 'express', 'http']) [host, port] = ["0.0.0.0", process.env.port or 5000] server = http.createserver(express().use(express.static( dirname))) sio.listen(server).sockets.on('connection', (socket)-> term = pty.spawn 'bash', [], {cwd: process.env.home}.on 'data', (data)-> socket.emit('data', data).on 'exit', -> socket.emit('exit', {}) ) socket.on 'data', (data)-> term.write data.on 'resize', (data)-> term.resize(data.cols, data.rows).on 'disconnect', -> term.destroy() index.coffee server.listen port, host, -> console.log('server Listening on %s:%d', host, port)
Frontend Source 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id="terminal"></div> <script type="text/coffeescript"> term = new Terminal() term.on('data', (data)-> socket.emit('data', data)) term.open($('#terminal')[0]) socket = io.connect("#{location.protocol}//#{location.hostname}:#{location.port}").on('data', (data)-> term.write(data)) $(window).resize( -> term.sizetofit() socket.emit('resize', -> cols: term.cols, rows: term.rows ) ) $ -> $(window).trigger('resize') </script> index.html
Demo on Coding.NET upload project quickly share with URL deploy by one key
Embedded in Docker Container
Mac OS Browser boot2docker TinyCore linux WebSocket client HTTP 5000 TCP 5000 WebSocket Server pty master Terminal emulator bash container pty slave Virtual Box VM
Dockerfile 1 2 3 4 5 6 7 8 9 10 FROM dockerfile/nodejs MAINTAINER Vangie Du <duwan@coding.net> EXPOSE 5000 ADD *.json index.*./ RUN npm install && bower install --allow-root CMD ["npm", "start"]
$ docker build -t "vangie/docker-web-terminal" --rm. $ docker run -d -p 5000:5000 vangie/docker-web-terminal:latest $ open http://`boot2docker ip`:5000
Source Code https://coding.net/u/duwan/p/docker-webterminal References The TTY demystified The Linux Programming Interface ISBN-13:978-1-59327-220-3 http://en.wikipedia.org/wiki/line_discipline
Thank You!