Skip to content

Commit

Permalink
refactor: Improve SSH command generation in Terminal.php and terminal…
Browse files Browse the repository at this point in the history
…-server.js
  • Loading branch information
andrasbacsai committed Oct 2, 2024
1 parent 0ab432d commit e03e4f2
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 9 deletions.
4 changes: 2 additions & 2 deletions app/Livewire/Project/Shared/Terminal.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ public function sendTerminalCommand($isContainer, $identifier, $serverUuid)
if ($status !== 'running') {
return;
}
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$identifier} sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$identifier} sh -c 'PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
} else {
$command = SshMultiplexingHelper::generateSshCommand($server, "sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
$command = SshMultiplexingHelper::generateSshCommand($server, 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n "$SHELL" ]; then exec $SHELL; else sh; fi');
}

// ssh command is sent back to frontend then to websocket
Expand Down
47 changes: 41 additions & 6 deletions docker/coolify-realtime/terminal-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,37 @@ const verifyClient = async (info, callback) => {

const wss = new WebSocketServer({ server, path: '/terminal/ws', verifyClient: verifyClient });
const userSessions = new Map();
let inactivityTimer;
const inactivityTime = 60 * 1000;
const inactivityInterval = 10 * 1000;

wss.on('connection', (ws) => {
const userId = generateUserId();
const userSession = { ws, userId, ptyProcess: null, isActive: false };
const userSession = { ws, userId, ptyProcess: null, isActive: false, lastActivityTime: Date.now() };
userSessions.set(userId, userSession);

ws.on('message', (message) => handleMessage(userSession, message));
// ws.on('pong', () => {
// console.log('pong');
// userSession.lastActivityTime = Date.now();
// clearInterval(inactivityTimer);
// inactivityTimer = setInterval(() => {
// const inactiveTime = Date.now() - userSession.lastActivityTime;
// console.log('inactiveTime', inactiveTime);
// if (inactiveTime > inactivityTime) {
// killPtyProcess(userId);
// clearInterval(inactivityTimer);
// }
// }, inactivityInterval);
// });

ws.on('message', (message) => {
handleMessage(userSession, message);
userSession.lastActivityTime = Date.now();

});
ws.on('error', (err) => handleError(err, userId));
ws.on('close', () => handleClose(userId));

});

const messageHandlers = {
Expand Down Expand Up @@ -108,7 +130,6 @@ function parseMessage(message) {

async function handleCommand(ws, command, userId) {
const userSession = userSessions.get(userId);

if (userSession && userSession.isActive) {
const result = await killPtyProcess(userId);
if (!result) {
Expand Down Expand Up @@ -139,13 +160,27 @@ async function handleCommand(ws, command, userId) {

ws.send('pty-ready');

ptyProcess.onData((data) => ws.send(data));
ptyProcess.onData((data) => {
ws.send(data);
// userSession.lastActivityTime = Date.now();
// clearInterval(inactivityTimer);
// inactivityTimer = setInterval(() => {
// const inactiveTime = Date.now() - userSession.lastActivityTime;
// console.log('inactiveTime', inactiveTime);
// if (inactiveTime > inactivityTime) {
// killPtyProcess(userId);
// clearInterval(inactivityTimer);
// }
// }, inactivityInterval);
});

// when parent closes
ptyProcess.onExit(({ exitCode, signal }) => {
console.error(`Process exited with code ${exitCode} and signal ${signal}`);
ws.send('pty-exited');
userSession.isActive = false;
// clearInterval(inactivityTimer);

});

if (timeout) {
Expand Down Expand Up @@ -179,7 +214,7 @@ async function killPtyProcess(userId) {

// session.ptyProcess.kill() wont work here because of https://github.com/moby/moby/issues/9098
// patch with https://github.com/moby/moby/issues/9098#issuecomment-189743947
session.ptyProcess.write('kill -TERM -$$ && exit\n');
session.ptyProcess.write('set +o history\nkill -TERM -$$ && exit\nset -o history\n');

setTimeout(() => {
if (!session.isActive || !session.ptyProcess) {
Expand Down Expand Up @@ -228,5 +263,5 @@ function extractHereDocContent(commandString) {
}

server.listen(6002, () => {
console.log('Server listening on port 6002');
console.log('Coolify realtime terminal server listening on port 6002. Let the hacking begin!');
});
22 changes: 21 additions & 1 deletion resources/js/terminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function initializeTerminalComponent() {
paused: false,
MAX_PENDING_WRITES: 5,
keepAliveInterval: null,
reconnectInterval: null,

init() {
this.setupTerminal();
Expand Down Expand Up @@ -48,6 +49,9 @@ export function initializeTerminalComponent() {
document.addEventListener(event, () => {
this.checkIfProcessIsRunningAndKillIt();
clearInterval(this.keepAliveInterval);
if (this.reconnectInterval) {
clearInterval(this.reconnectInterval);
}
}, { once: true });
});

Expand Down Expand Up @@ -103,11 +107,27 @@ export function initializeTerminalComponent() {
};
this.socket.onclose = () => {
console.log('WebSocket connection closed');

this.reconnect();
};
}
},

reconnect() {
if (this.reconnectInterval) {
clearInterval(this.reconnectInterval);
}
this.reconnectInterval = setInterval(() => {
console.log('Attempting to reconnect...');
this.initializeWebSocket();
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
console.log('Reconnected successfully');
clearInterval(this.reconnectInterval);
this.reconnectInterval = null;
window.location.reload();
}
}, 5000);
},

handleSocketMessage(event) {
this.message = '(connection closed)';
if (event.data === 'pty-ready') {
Expand Down

0 comments on commit e03e4f2

Please sign in to comment.