test
This commit is contained in:
parent
fc7542db6b
commit
a86f14fce8
146
RAM_MONITOR_README.md
Normal file
146
RAM_MONITOR_README.md
Normal file
@ -0,0 +1,146 @@
|
||||
# 🔍 Moniteur de RAM - Palworld Server
|
||||
|
||||
## Description
|
||||
|
||||
Le moniteur de RAM surveille automatiquement l'utilisation de la mémoire du serveur Palworld. Lorsque le seuil de **19 Go** est dépassé, le serveur est automatiquement redémarré pour éviter les problèmes de performance ou de crash.
|
||||
|
||||
## Fonctionnalités
|
||||
|
||||
### Surveillance automatique
|
||||
- ✅ Vérification de la RAM toutes les 60 secondes
|
||||
- ✅ Seuil de déclenchement : **19 Go**
|
||||
- ✅ Redémarrage automatique si le seuil est dépassé
|
||||
- ✅ Resynchronisation automatique du WebSocket après redémarrage
|
||||
|
||||
### Processus de redémarrage
|
||||
Lorsque le seuil est atteint, le système effectue les étapes suivantes :
|
||||
|
||||
1. 💾 **Sauvegarde** du serveur
|
||||
2. 📢 **Annonce** aux joueurs (broadcast : "Redémarrage automatique - RAM élevée - 30 secondes")
|
||||
3. ⏹️ **Arrêt** du serveur (signal stop)
|
||||
4. ⏳ **Attente** de 25 secondes
|
||||
5. 🚀 **Redémarrage** du serveur (signal start)
|
||||
6. ⏳ **Vérification** jusqu'à ce que le serveur soit opérationnel
|
||||
7. 🔄 **Resynchronisation** du WebSocket (après 5 secondes supplémentaires)
|
||||
|
||||
### Commande Discord
|
||||
|
||||
#### `/ram-status`
|
||||
Affiche l'état actuel de la RAM du serveur.
|
||||
|
||||
**Permissions requises :** Rôle Rygainland
|
||||
|
||||
**Informations affichées :**
|
||||
- 📊 Utilisation actuelle (en Go et pourcentage)
|
||||
- ⚠️ Seuil de redémarrage configuré
|
||||
- 🔄 État du serveur (running, stopped, etc.)
|
||||
- 💡 Niveau d'alerte (Normal 🟢 / Élevé 🟡 / Critique 🔴)
|
||||
- ✅ État de la surveillance automatique
|
||||
|
||||
**Exemple d'affichage :**
|
||||
```
|
||||
🟢 État de la RAM du serveur Palworld
|
||||
|
||||
📊 Utilisation actuelle: 15.32 Go / 19.00 Go (80.6%)
|
||||
⚠️ Seuil de redémarrage: 19.00 Go
|
||||
🔄 État du serveur: running
|
||||
💡 Niveau: Élevée
|
||||
|
||||
✅ Surveillance automatique active
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Variables d'environnement requises
|
||||
|
||||
Le moniteur utilise les variables d'environnement suivantes (déjà configurées) :
|
||||
|
||||
```env
|
||||
PTERODACTYL_API_URL=https://panel.louismazin.ovh
|
||||
PTERODACTYL_API_TOKEN=votre_token
|
||||
PTERODACTYL_SERVER_ID=ae4a628f
|
||||
```
|
||||
|
||||
### Paramètres modifiables
|
||||
|
||||
Dans le fichier `ramMonitor.js` :
|
||||
|
||||
```javascript
|
||||
const RAM_THRESHOLD_MB = 19 * 1024; // Seuil en MB (19 Go par défaut)
|
||||
const CHECK_INTERVAL_MS = 60 * 1000; // Intervalle de vérification (60 secondes)
|
||||
```
|
||||
|
||||
## Intégration
|
||||
|
||||
### Fichiers modifiés/créés
|
||||
|
||||
1. **`ramMonitor.js`** (nouveau)
|
||||
- Module principal de surveillance
|
||||
- Gestion du redémarrage automatique
|
||||
|
||||
2. **`index.js`** (modifié)
|
||||
- Ajout de `startRAMMonitoring(forceWebSocketReconnect)`
|
||||
- Import du module ramMonitor
|
||||
|
||||
3. **`consoleMonitor.js`** (modifié)
|
||||
- Ajout de la fonction `forceWebSocketReconnect()`
|
||||
- Export de la fonction pour utilisation par ramMonitor
|
||||
|
||||
4. **`commands/server/ram-status.js`** (nouveau)
|
||||
- Commande Discord pour consulter l'état de la RAM
|
||||
|
||||
## Logs
|
||||
|
||||
Le moniteur affiche des logs détaillés dans la console :
|
||||
|
||||
```
|
||||
🚀 [RAM Monitor] Démarrage de la surveillance RAM (seuil: 19 Go)
|
||||
⏱️ [RAM Monitor] Intervalle de vérification: 60s
|
||||
🔍 [RAM Monitor] Utilisation RAM: 15.32 Go / État: running
|
||||
⚠️ [RAM Monitor] SEUIL DÉPASSÉ ! 19.54 Go > 19 Go
|
||||
🔄 [RAM Monitor] Déclenchement du redémarrage automatique...
|
||||
💾 [RAM Monitor] Sauvegarde du serveur...
|
||||
📢 [RAM Monitor] Annonce du redémarrage...
|
||||
⏹️ [RAM Monitor] Arrêt du serveur...
|
||||
⏳ [RAM Monitor] Attente de 25 secondes...
|
||||
🚀 [RAM Monitor] Redémarrage du serveur...
|
||||
✅ [RAM Monitor] Serveur redémarré avec succès !
|
||||
🔄 [RAM Monitor] Resynchronisation du WebSocket...
|
||||
```
|
||||
|
||||
## Sécurité
|
||||
|
||||
- 🔒 Un seul redémarrage ne peut être en cours à la fois (protection via flag `isRebooting`)
|
||||
- 🔒 Timeout maximum de 2.5 minutes pour le redémarrage
|
||||
- 🔒 Vérification de l'état du serveur avant déclenchement (doit être `running`)
|
||||
- 🔒 Commande Discord protégée par rôle
|
||||
|
||||
## Notes techniques
|
||||
|
||||
- Le serveur Pterodactyl fournit `memory_bytes` qui est converti en Mo puis Go
|
||||
- La surveillance ne se déclenche que si le serveur est en état `running`
|
||||
- Le WebSocket est resynchronisé après 5 secondes de stabilisation post-redémarrage
|
||||
- Les websockets existants sont proprement fermés avant reconnexion
|
||||
|
||||
## Dépannage
|
||||
|
||||
### La surveillance ne démarre pas
|
||||
- Vérifier les variables d'environnement `PTERODACTYL_API_TOKEN` et `PTERODACTYL_SERVER_ID`
|
||||
- Vérifier les permissions API Pterodactyl
|
||||
|
||||
### Le redémarrage ne se déclenche pas
|
||||
- Vérifier que le seuil est correctement configuré
|
||||
- Consulter les logs pour voir l'utilisation actuelle
|
||||
- Utiliser `/ram-status` pour diagnostiquer
|
||||
|
||||
### Le WebSocket ne se reconnecte pas
|
||||
- Vérifier que `consoleMonitor.js` est bien démarré
|
||||
- Les logs indiqueront les tentatives de reconnexion
|
||||
|
||||
## Désactivation
|
||||
|
||||
Pour désactiver temporairement la surveillance, commenter dans `index.js` :
|
||||
|
||||
```javascript
|
||||
// startRAMMonitoring(forceWebSocketReconnect);
|
||||
```
|
||||
60
commands/server/ram-status.js
Normal file
60
commands/server/ram-status.js
Normal file
@ -0,0 +1,60 @@
|
||||
const { SlashCommandBuilder } = require('discord.js');
|
||||
const { checkRAMUsage, getMonitoringStatus } = require('../../ramMonitor.js');
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('ram-status')
|
||||
.setDescription('Affiche l\'utilisation actuelle de la RAM du serveur Palworld'),
|
||||
async execute(interaction) {
|
||||
|
||||
if (!interaction.member.roles.cache.has('1444684935632912394')) {
|
||||
await interaction.reply({ content: '❌ Il faut avoir le rôle Rygainland pour pouvoir utiliser cette commande.', flags: 64 });
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.deferReply();
|
||||
|
||||
try {
|
||||
// Récupérer les informations sur la RAM
|
||||
const ramInfo = await checkRAMUsage();
|
||||
const monitorStatus = getMonitoringStatus();
|
||||
|
||||
if (!ramInfo) {
|
||||
await interaction.editReply('❌ Impossible de récupérer les informations de RAM du serveur.');
|
||||
return;
|
||||
}
|
||||
|
||||
const { ramUsedGB, currentState } = ramInfo;
|
||||
const thresholdGB = (monitorStatus.threshold / 1024).toFixed(2);
|
||||
const percentUsed = ((ramInfo.ramUsedMB / monitorStatus.threshold) * 100).toFixed(1);
|
||||
|
||||
// Construire le message avec indicateur visuel
|
||||
let indicator;
|
||||
let color;
|
||||
if (percentUsed < 70) {
|
||||
indicator = '🟢';
|
||||
color = 'Normale';
|
||||
} else if (percentUsed < 90) {
|
||||
indicator = '🟡';
|
||||
color = 'Élevée';
|
||||
} else {
|
||||
indicator = '🔴';
|
||||
color = 'Critique';
|
||||
}
|
||||
|
||||
const message = `${indicator} **État de la RAM du serveur Palworld**\n\n` +
|
||||
`📊 **Utilisation actuelle:** ${ramUsedGB} Go / ${thresholdGB} Go (${percentUsed}%)\n` +
|
||||
`⚠️ **Seuil de redémarrage:** ${thresholdGB} Go\n` +
|
||||
`🔄 **État du serveur:** ${currentState}\n` +
|
||||
`💡 **Niveau:** ${color}\n\n` +
|
||||
`${monitorStatus.isMonitoring ? '✅ Surveillance automatique active' : '⚠️ Surveillance automatique inactive'}\n` +
|
||||
`${monitorStatus.isRebooting ? '🔄 Redémarrage en cours...' : ''}`;
|
||||
|
||||
await interaction.editReply(message);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération de l\'état RAM:', error);
|
||||
await interaction.editReply('❌ Erreur lors de la récupération des informations du serveur.');
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -522,4 +522,10 @@ const stopConsoleMonitoring = () => {
|
||||
console.log('🔌 Surveillance de la console arrêtée');
|
||||
};
|
||||
|
||||
module.exports = { startConsoleMonitoring, stopConsoleMonitoring };
|
||||
// Fonction pour forcer la reconnexion du WebSocket (utilisée par ramMonitor)
|
||||
const forceWebSocketReconnect = async () => {
|
||||
console.log('🔄 [CONSOLE] Reconnexion forcée du WebSocket...');
|
||||
await forceReconnectToRefreshCredentials();
|
||||
};
|
||||
|
||||
module.exports = { startConsoleMonitoring, stopConsoleMonitoring, forceWebSocketReconnect };
|
||||
|
||||
7
index.js
7
index.js
@ -7,8 +7,9 @@ const update = require('./displayer.js');
|
||||
const clean = require('./cleaner.js');
|
||||
const { Client, GatewayIntentBits, Collection, Events, Partials } = require('discord.js');
|
||||
const { initDatabase, createTables, cleanExpiredCodes } = require('./database.js');
|
||||
const { startConsoleMonitoring } = require('./consoleMonitor.js');
|
||||
const { startConsoleMonitoring, forceWebSocketReconnect } = require('./consoleMonitor.js');
|
||||
const { initPalworldBridge } = require('./palworld-bridge.js');
|
||||
const { startRAMMonitoring } = require('./ramMonitor.js');
|
||||
|
||||
const client = new Client({ intents:
|
||||
[
|
||||
@ -82,6 +83,10 @@ client.once('ready', async () => {
|
||||
}
|
||||
|
||||
startConsoleMonitoring(client, process.env.PTERODACTYL_API_TOKEN);
|
||||
|
||||
// Démarrer la surveillance RAM avec callback de reconnexion WebSocket
|
||||
startRAMMonitoring(forceWebSocketReconnect);
|
||||
console.log('✅ Surveillance RAM activée (seuil: 19 Go)');
|
||||
} catch (error) {
|
||||
console.error('⚠️ Erreur lors de l\'initialisation de la base de données');
|
||||
console.error('⚠️ Le système de liaison est désactivé');
|
||||
|
||||
199
ramMonitor.js
Normal file
199
ramMonitor.js
Normal file
@ -0,0 +1,199 @@
|
||||
const axios = require('axios');
|
||||
|
||||
let isMonitoring = false;
|
||||
let checkInterval = null;
|
||||
let isRebooting = false;
|
||||
let reconnectCallback = null; // Callback pour resync le WebSocket
|
||||
|
||||
const RAM_THRESHOLD_MB = 19 * 1024; // 19 Go en MB
|
||||
const CHECK_INTERVAL_MS = 60 * 1000; // Vérifier toutes les 60 secondes
|
||||
|
||||
/**
|
||||
* Vérifie l'utilisation actuelle de la RAM du serveur
|
||||
*/
|
||||
const checkRAMUsage = async () => {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${process.env.PTERODACTYL_API_URL}/api/client/servers/${process.env.PTERODACTYL_SERVER_ID}/resources`,
|
||||
{
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${process.env.PTERODACTYL_API_TOKEN}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const resources = response.data.attributes.resources;
|
||||
const ramUsedMB = resources.memory_bytes / (1024 * 1024); // Convertir en MB
|
||||
const ramUsedGB = (ramUsedMB / 1024).toFixed(2); // Convertir en GB pour l'affichage
|
||||
const currentState = response.data.attributes.current_state;
|
||||
|
||||
console.log(`🔍 [RAM Monitor] Utilisation RAM: ${ramUsedGB} Go / État: ${currentState}`);
|
||||
|
||||
// Vérifier si on dépasse le seuil ET que le serveur est en cours d'exécution
|
||||
if (ramUsedMB > RAM_THRESHOLD_MB && currentState === 'running' && !isRebooting) {
|
||||
console.log(`⚠️ [RAM Monitor] SEUIL DÉPASSÉ ! ${ramUsedGB} Go > 19 Go`);
|
||||
console.log(`🔄 [RAM Monitor] Déclenchement du redémarrage automatique...`);
|
||||
|
||||
await rebootServer();
|
||||
}
|
||||
|
||||
return { ramUsedMB, ramUsedGB, currentState };
|
||||
} catch (error) {
|
||||
console.error('❌ [RAM Monitor] Erreur lors de la vérification RAM:', error.message);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Redémarre le serveur automatiquement
|
||||
*/
|
||||
const rebootServer = async () => {
|
||||
if (isRebooting) {
|
||||
console.log('⚠️ [RAM Monitor] Redémarrage déjà en cours, annulation...');
|
||||
return;
|
||||
}
|
||||
|
||||
isRebooting = true;
|
||||
|
||||
try {
|
||||
const headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${process.env.PTERODACTYL_API_TOKEN}`
|
||||
};
|
||||
|
||||
const serverUrl = `${process.env.PTERODACTYL_API_URL}/api/client/servers/${process.env.PTERODACTYL_SERVER_ID}`;
|
||||
|
||||
console.log('💾 [RAM Monitor] Sauvegarde du serveur...');
|
||||
await axios.post(`${serverUrl}/command`, {
|
||||
command: 'save'
|
||||
}, { headers });
|
||||
|
||||
// Annoncer le redémarrage aux joueurs
|
||||
console.log('📢 [RAM Monitor] Annonce du redémarrage...');
|
||||
await axios.post(`${serverUrl}/command`, {
|
||||
command: "broadcast 'Redémarrage automatique (RAM élevée - 30 secondes)'"
|
||||
}, { headers });
|
||||
|
||||
// Attendre la sauvegarde
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
console.log('⏹️ [RAM Monitor] Arrêt du serveur...');
|
||||
await axios.post(`${serverUrl}/power`, {
|
||||
signal: 'stop'
|
||||
}, { headers });
|
||||
|
||||
// Attendre 25 secondes
|
||||
console.log('⏳ [RAM Monitor] Attente de 25 secondes...');
|
||||
await new Promise(resolve => setTimeout(resolve, 25000));
|
||||
|
||||
console.log('🚀 [RAM Monitor] Redémarrage du serveur...');
|
||||
await axios.post(`${serverUrl}/power`, {
|
||||
signal: 'start'
|
||||
}, { headers });
|
||||
|
||||
// Attendre que le serveur soit opérationnel
|
||||
let isRunning = false;
|
||||
let attempts = 0;
|
||||
const maxAttempts = 30; // 30 tentatives * 5 secondes = 2.5 minutes max
|
||||
|
||||
while (!isRunning && attempts < maxAttempts) {
|
||||
attempts++;
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
try {
|
||||
const checkResponse = await axios.get(`${serverUrl}/resources`, { headers });
|
||||
const state = checkResponse.data.attributes.current_state;
|
||||
|
||||
if (state === 'running') {
|
||||
isRunning = true;
|
||||
console.log('✅ [RAM Monitor] Serveur redémarré avec succès !');
|
||||
|
||||
// Resynchroniser le WebSocket si un callback est défini
|
||||
if (reconnectCallback) {
|
||||
console.log('🔄 [RAM Monitor] Resynchronisation du WebSocket...');
|
||||
await new Promise(resolve => setTimeout(resolve, 5000)); // Attendre 5s de plus
|
||||
reconnectCallback();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ [RAM Monitor] Tentative ${attempts}/${maxAttempts} échouée:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRunning) {
|
||||
console.error('❌ [RAM Monitor] Le serveur n\'a pas redémarré après le délai maximum');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ [RAM Monitor] Erreur lors du redémarrage:', error.message);
|
||||
} finally {
|
||||
isRebooting = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Démarre la surveillance de la RAM
|
||||
*/
|
||||
const startRAMMonitoring = (websocketReconnectCallback = null) => {
|
||||
if (isMonitoring) {
|
||||
console.log('⚠️ [RAM Monitor] Surveillance déjà active');
|
||||
return;
|
||||
}
|
||||
|
||||
reconnectCallback = websocketReconnectCallback;
|
||||
|
||||
console.log(`🚀 [RAM Monitor] Démarrage de la surveillance RAM (seuil: 19 Go)`);
|
||||
console.log(`⏱️ [RAM Monitor] Intervalle de vérification: ${CHECK_INTERVAL_MS / 1000}s`);
|
||||
|
||||
isMonitoring = true;
|
||||
|
||||
// Première vérification immédiate
|
||||
checkRAMUsage();
|
||||
|
||||
// Vérifications périodiques
|
||||
checkInterval = setInterval(async () => {
|
||||
if (!isRebooting) {
|
||||
await checkRAMUsage();
|
||||
}
|
||||
}, CHECK_INTERVAL_MS);
|
||||
};
|
||||
|
||||
/**
|
||||
* Arrête la surveillance de la RAM
|
||||
*/
|
||||
const stopRAMMonitoring = () => {
|
||||
if (!isMonitoring) {
|
||||
console.log('⚠️ [RAM Monitor] Surveillance déjà inactive');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('⏹️ [RAM Monitor] Arrêt de la surveillance RAM');
|
||||
isMonitoring = false;
|
||||
|
||||
if (checkInterval) {
|
||||
clearInterval(checkInterval);
|
||||
checkInterval = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtenir le statut de la surveillance
|
||||
*/
|
||||
const getMonitoringStatus = () => {
|
||||
return {
|
||||
isMonitoring,
|
||||
isRebooting,
|
||||
threshold: RAM_THRESHOLD_MB,
|
||||
checkInterval: CHECK_INTERVAL_MS
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
startRAMMonitoring,
|
||||
stopRAMMonitoring,
|
||||
checkRAMUsage,
|
||||
getMonitoringStatus
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user