Add safe shudown
- SIGINT is intercepted and force-quits the 2nd time - Live countdown on Web UI - Countdown ignored if all clients disconnect - Clean exit function
This commit is contained in:
parent
7a89d45e48
commit
eb7d91ffbc
7 changed files with 111 additions and 1 deletions
|
@ -19,6 +19,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="footer"></div>
|
<div id="footer"></div>
|
||||||
<div id="status"></div>
|
<div id="status"></div>
|
||||||
|
<div id="countdown"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/ssh/webssh2.bundle.js" defer></script>
|
<script src="/ssh/webssh2.bundle.js" defer></script>
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -246,6 +246,30 @@ body, html {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
#countdown {
|
||||||
|
display: none;
|
||||||
|
color: rgb(240, 240, 240);
|
||||||
|
background-color: rgb(50, 50, 50);
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
border-color: white;
|
||||||
|
border-style: none solid none solid;
|
||||||
|
border-width: 1px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
#countdown.active {
|
||||||
|
display: inline-block;
|
||||||
|
animation: countdown infinite alternate 200ms;
|
||||||
|
}
|
||||||
|
@keyframes countdown {
|
||||||
|
from {
|
||||||
|
background-color: rgb(255, 255, 0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
#menu {
|
#menu {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="footer"></div>
|
<div id="footer"></div>
|
||||||
<div id="status"></div>
|
<div id="status"></div>
|
||||||
|
<div id="countdown"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/ssh/webssh2.bundle.js" defer></script>
|
<script src="/ssh/webssh2.bundle.js" defer></script>
|
||||||
|
|
|
@ -75,6 +75,30 @@ body, html {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
#countdown {
|
||||||
|
display: none;
|
||||||
|
color: rgb(240, 240, 240);
|
||||||
|
background-color: rgb(50, 50, 50);
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
border-color: white;
|
||||||
|
border-style: none solid none solid;
|
||||||
|
border-width: 1px;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
#countdown.active {
|
||||||
|
display: inline-block;
|
||||||
|
animation: countdown infinite alternate 200ms;
|
||||||
|
}
|
||||||
|
@keyframes countdown {
|
||||||
|
from {
|
||||||
|
background-color: rgb(255, 255, 0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
#menu {
|
#menu {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
|
@ -26,6 +26,7 @@ var status = document.getElementById('status')
|
||||||
var header = document.getElementById('header')
|
var header = document.getElementById('header')
|
||||||
var dropupContent = document.getElementById('dropupContent')
|
var dropupContent = document.getElementById('dropupContent')
|
||||||
var footer = document.getElementById('footer')
|
var footer = document.getElementById('footer')
|
||||||
|
var countdown = document.getElementById('countdown')
|
||||||
var fitAddon = new FitAddon()
|
var fitAddon = new FitAddon()
|
||||||
var terminalContainer = document.getElementById('terminal-container')
|
var terminalContainer = document.getElementById('terminal-container')
|
||||||
term.loadAddon(fitAddon)
|
term.loadAddon(fitAddon)
|
||||||
|
@ -136,6 +137,7 @@ socket.on('disconnect', function (err) {
|
||||||
'WEBSOCKET SERVER DISCONNECTED: ' + err
|
'WEBSOCKET SERVER DISCONNECTED: ' + err
|
||||||
}
|
}
|
||||||
socket.io.reconnection(false)
|
socket.io.reconnection(false)
|
||||||
|
countdown.classList.remove('active')
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('error', function (err) {
|
socket.on('error', function (err) {
|
||||||
|
@ -149,6 +151,18 @@ socket.on('reauth', function () {
|
||||||
(allowreauth) && reauthSession()
|
(allowreauth) && reauthSession()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// safe shutdown
|
||||||
|
var hasCountdownStarted = false
|
||||||
|
|
||||||
|
socket.on('shutdownCountdownUpdate', function (remainingSeconds) {
|
||||||
|
if (!hasCountdownStarted) {
|
||||||
|
countdown.classList.add('active')
|
||||||
|
hasCountdownStarted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
countdown.innerText = 'Shutting down in ' + remainingSeconds + 's'
|
||||||
|
})
|
||||||
|
|
||||||
term.onTitleChange(function (title) {
|
term.onTitleChange(function (title) {
|
||||||
document.title = title
|
document.title = title
|
||||||
})
|
})
|
||||||
|
|
|
@ -199,4 +199,50 @@ io.use(function (socket, next) {
|
||||||
// bring up socket
|
// bring up socket
|
||||||
io.on('connection', socket)
|
io.on('connection', socket)
|
||||||
|
|
||||||
|
// safe shutdown
|
||||||
|
var shutdownMode = false
|
||||||
|
var shutdownInterval = 0
|
||||||
|
var connectionCount = 0
|
||||||
|
|
||||||
|
io.on('connection', function (socket) {
|
||||||
|
connectionCount++
|
||||||
|
|
||||||
|
socket.on('disconnect', function () {
|
||||||
|
if ((--connectionCount <= 0) && shutdownMode) {
|
||||||
|
stop('All clients disconnected')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('SIGINT', function () {
|
||||||
|
if (shutdownMode) stop('Safe shutdown aborted, force quitting')
|
||||||
|
else if (connectionCount > 0) {
|
||||||
|
var remainingSeconds = 300
|
||||||
|
shutdownMode = true
|
||||||
|
|
||||||
|
var message = (connectionCount === 1) ? ' client is still connected'
|
||||||
|
: ' clients are still connected'
|
||||||
|
console.error(connectionCount + message)
|
||||||
|
console.error('Starting a ' + remainingSeconds + ' seconds countdown')
|
||||||
|
console.error('Press Ctrl+C again to force quit')
|
||||||
|
|
||||||
|
shutdownInterval = setInterval(function () {
|
||||||
|
if ((remainingSeconds--) <= 0) {
|
||||||
|
stop('Countdown is over')
|
||||||
|
} else {
|
||||||
|
io.sockets.emit('shutdownCountdownUpdate', remainingSeconds)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
} else stop()
|
||||||
|
})
|
||||||
|
|
||||||
|
// clean stop
|
||||||
|
function stop (reason) {
|
||||||
|
shutdownMode = false
|
||||||
|
if (reason) console.log('Stopping: ' + reason)
|
||||||
|
if (shutdownInterval) clearInterval(shutdownInterval)
|
||||||
|
io.close()
|
||||||
|
server.close()
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = { server: server, config: config }
|
module.exports = { server: server, config: config }
|
||||||
|
|
Loading…
Reference in a new issue