[TUTO] Création d'une RamDisk && Suppression des LAGs

  • Auteur de la discussion Auteur de la discussion Nkio
  • Date de début Date de début

Nkio

Bucheron
29 Septembre 2011
148
3
13
37
Une RamDisk permet de faire croire à l'OS qu'une partie de la RAM est un disque dur et de l'utiliser comme tel.
Ce TUTO demande une certaine connaissance des commandes Linux dans son ensemble. Il n'est pas applicable au simple serveur héberger par un tiers, il vous faut un serveur dédié avec une jolie console/connexion à distance avec une interface.

Dans tout les cas soyés bien a l'aise avec les commandes cd / chown /echo /sleep / rsync et le Script Shell entre autre, sinon vous allez être vite dépassé. Il vous faudra aussi screen, mais ça je pense que vous l'avez déjà.

Bien entendu la RAM est volatile, donc par conséquent, ne faite pas ça sur un serveur ou vous tester des plugins, car si vous coupez violemment votre serveur car un plugin déconne, d'une, en temps normal c'est fortement déconseillé (Vive les corruptions de map), et deuxièmement, avec une RamDisk vous allez perdre la totalité des dernière minutes ,+ une petite corruption des données si le serveur était entrain de se synchroniser avec la map présente sur le disque dur.

Pour info la RAM permet d'écrire des données jusqu'à 10664 MB/S pour de la DDR3-1333, un poil plus rapide qu'un disque dur.

On part du principe que vous avez screen d'installer, sans lui de tout façon il serais compliquer de lancer le serveur minecraft et de le laisser tourner sur le serveur dès que vous quittez votre connexion ssh.

Je présume que vous avec un utilisateur dédié pour votre serveur minecraft et que vous n'avez pas lancer votre serveur avec l'utilisateur root. (il faudrait être fou).

Si ce n'est pas le cas, ouvrez une console et tapez :
Code:
adduser --disabled-login minecraft

Noter l'endroit ou vous avez créer votre serveur minecraft, sinon vous pouvez faire
Code:
mkdir /opt/minecraft

Ensuite nous ajoutons les droits de l'utilisateur sur ce dossier
Code:
chown -R minecraft /opt/minecraft

On va commencer à rentrer dans le vif du sujet. Créez un fichier minecraft avec votre éditeur préférer (Emacs, Vi ......) et ajoutez y ceci.
Code:
#!/bin/bash
# /etc/init.d/minecraft

# Provides: minecraft
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start: $network
# Should-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Minecraft server

#################Configuration################

# Nom de votre fichier JAR (craftbukkit-1.0.0-SNAPSHOT.jar pour la bukkit 1.0.0)
SERVICE="craftbukkit-0.0.1-SNAPSHOT.jar"

# Nom de l'instance de screen
SCREEN="minecraft"

# Utilisateur qui peut lancer votre serveur
USERNAME="minecraft"

# Path de votre répertoire Minecraft
MCPATH="/opt/minecraft"

# Nom de CPU utilisés, a vous de changer la valeur survant votre machine
CPU_COUNT=2

# Mémoire alloué au démarrage de Java
INITMEM="2048M"

# Maximum de mémoire alloué à Java
MAXMEM="10240M"

#Ligne de démarrge de votre serveur
INVOCATION="java -Xmx$MAXMEM -Xms$INITMEM -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=$CPU_COUNT -XX:+AggressiveOpts -jar $SERVICE nogui"

#Mise à jour de bukkit version instable 1.0.0
DOWNLOADURL="http://ci.bukkit.org/job/dev-CraftBukkit/lastStableBuild/artifact/target/craftbukkit-1.0.0-SNAPSHOT.jar"

#Mise à jour de bukkit version recommandé
DOWNLOADURL="http://ci.bukkit.org/job/dev-CraftBukkit/Recommended/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar"

# Dossier de sauvegarde de votre monde
BACKUPPATH="${MCPATH}/backup_world"

# Copie des Logs
LOGPATH="${MCPATH}/logs"

# Dossier ou le serveur est sauvegarder dans son ensemble
WHOLEBACKUP="${MCPATH}/backup_serv"

# Emplacement des mondes.
WORLDSTORAGE="${MCPATH}/worldstorage"

# Path ou est monté la ramdisk Par défaut sous Ubuntu: /dev/shm
RAMDISK="/dev/shm"

# Format des backups, vous pouvez mettre aussi zip
BACKUPFORMAT="tar"

Ça fait déjà un bon petit début, si vous avez des questions ....

Dans le même fichier, on ajoute les ligne suivante pour vérifier qu'il s'agit bien de l'utilisateur nommé qui tape les commandes
Code:
ME=`whoami`
as_user() {
  if [ "$ME" == "$USERNAME" ] ;
  then
    bash -c "$1"
  else
    su - $USERNAME -c "$1"
  fi
}

On récupère la date (ça va aider pour les sauvegardes)
Code:
datepath() {
if [ -e $1`date +%F`$2 ]
then
  echo $1`date +%FT%T`$3
else
  echo $1`date +%F`$3
fi
}

Pour ceux qui n'ont pas forcement les connaissant en shell, tout les commande effectué entre backquote `` sont exécuté et le résultat renvoyer dans d'autre commande.

Ici nous avons commencé par mettre la variable $USERNAME que vous avez défini plus tôt dans la variable $1, ensuite nous avons demandé à récupérer la date qui est stocker dans $3 avec la variable $1+date

Ensuite nous allons lancer la bête :p. Évitez de mettre des accents
Code:
mc_start() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE  est deja lance, impossible de le relancer"
    else
        echo "$SERVICE est inactif .... demarrage"
    cd $MCPATH
        as_user "cd $MCPATH && screen -dmS $SCREEN $INVOCATION"
    sleep 7
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE  est desormais lance"
    else
        echo "impossible de demarrer $SERVICE."
    fi
fi
}

Le sleep 7 permet d'attendre 7 secondes avant de vérifier que votre serveur est bien lancé. Si votre serveur mets plus de temps à démarrer suite à de nombreux plugins, augmentez légèrement la valeur.

Ensuite nous allons créer la fonction d'arrêt:
Code:
mc_stop() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE est lance..........Arret en cours."
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"save-all\"\015'"
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Une demande d arret a ete formule, le serveur sera stoppe dans 15 secondes\"\015'"
sleep 5
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur sera stoppe dans 10 secondes\"\015'"
sleep 5
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur sera stoppe dans 5 secondes\"\015'"*
sleep 1
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur sera stoppe dans 4 secondes\"\015'"
sleep 1
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur sera stoppe dans 3 secondes\"\015'"
sleep 1
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur sera stoppe dans 2 secondes\"\015'"
sleep 1
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur sera stoppe dans 1 secondes\"\015'"
sleep 2
    as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"stop\"\015'"
sleep 7
    else
        echo "$SERVICE est en cours d arret."
    fi
sleep 7
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE ne peut etre stoppe ....... $SERVICE est toujours actif."
        as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur est toujours actif, votre admin a fait une boulette, tapez le\"\015'"
    else
        echo "$SERVICE est stoppe"
fi
}

On va créer les fonctions de sauvegarde automatique et l'arrêt de celle-ci
Code:
mc_saveoff() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE est actif.....suspension des sauvegardes"
        as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"save-off\"\015'"
        as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"save-all\"\015'"
    sync
sleep 10
    else
        echo "$SERVICE est inactif, les sauvegarde ne sont pas suspendues"
fi
}

mc_saveon() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE est actif ...... activation des sauvegardes automatiques"
        as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"save-on\"\015'"
        as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"save-all\"\015'"
    else
        echo "$SERVICE est inactif ...... impossible de mettre en route les sauvegardes automatiques"
fi
}

Création des dossiers de log
Code:
log_roll() {
    as_user "mkdir -p $LOGPATH"
    path=`datepath $LOGPATH/server_ .log.gz .log`
    as_user "mv $MCPATH/server.log $path && gzip $path"
}

On récupère le world
Code:
get_worlds() {
a=1
for NAME in $(ls $WORLDSTORAGE)
    do
        if [ -d $WORLDSTORAGE/$NAME ]
    then
        WORLDNAME[$a]=$NAME
    if [ -e $WORLDSTORAGE/$NAME/ramdisk ]
        then
            WORLDRAM[$a]=true
    else
        WORLDRAM[$a]=false
    fi
        a=$a+1
    fi
done
}

On mets en place les fonctions de sauvegarde complète
Code:
mc_whole_backup() {
    as_user "mkdir -p $WHOLEBACKUP"
    path=`datepath $WHOLEBACKUP/mine_`
    as_user "cp -rP $MCPATH $path"
}
mc_world_backup() {
    get_worlds
for INDEX in ${!WORLDNAME[@]}
    do
        echo "Sauvegarde des mondes ${WORLDNAME[$INDEX]}"
        as_user "mkdir -p $BACKUPPATH"

    case "$BACKUPFORMAT" in
    tar)
        path=`datepath $BACKUPPATH/${WORLDNAME[$INDEX]}_ .tar.bz2 .tar.bz2`
        as_user "tar -hcjf $path $MCPATH/${WORLDNAME[$INDEX]}"
        ;;
    zip)
        path=`datepath $BACKUPPATH/${WORLDNAME[$INDEX]}_ .zip .zip`
        as_user "zip -rq $path $MCPATH/${WORLDNAME[$INDEX]}"
        ;;
    *)
echo "$BACKUPFORMAT n est pas un format correct"
    ;;
esac
done
}

On va rendre ça multiworld un petit peu :D
Code:
change_ramdisk_state() {
if [ ! -e $WORLDSTORAGE/$1 ]
then
echo "World \"$1\" non trouve."
exit 1
fi
if [ -e $WORLDSTORAGE/$1/ramdisk ]
then
rm $WORLDSTORAGE/$1/ramdisk
echo "suppression d un flag ramdisk \"$1\""
else
touch $WORLDSTORAGE/$1/ramdisk
echo "ajout d un flag ramdisk \"$1\""
fi
echo "Les changement seront pris en compte au redemarrage."
}

Création des lien entre la ram et le disque
Code:
check_links() {
get_worlds
    for INDEX in ${!WORLDNAME[@]}
        do
            if [[ -L $MCPATH/${WORLDNAME[$INDEX]} || ! -a $MCPATH/${WORLDNAME[$INDEX]} ]]
            then
            link=`ls -l $MCPATH/${WORLDNAME[$INDEX]} | awk '{print $11}'`
            if ${WORLDRAM[$INDEX]}
            then
            if [ "$link" != "$RAMDISK/${WORLDNAME[$INDEX]}" ]
            then
                as_user "rm -f $MCPATH/${WORLDNAME[$INDEX]}"
                as_user "ln -s $RAMDISK/${WORLDNAME[$INDEX]} $MCPATH/${WORLDNAME[$INDEX]}"
        echo "creation d un lien pour ${WORLDNAME[$INDEX]}"
    fi
else
    if [ "$link" != "${WORLDSTORAGE}/${WORLDNAME[$INDEX]}" ]
    then
        as_user "rm -f $MCPATH/${WORLDNAME[$INDEX]}"
        as_user "ln -s ${WORLDSTORAGE}/${WORLDNAME[$INDEX]} $MCPATH/${WORLDNAME[$INDEX]}"
    echo "creation d un lien pour ${WORLDNAME[$INDEX]}"
fi
fi
else
    echo "impossible d effectuer ${WORLDNAME[$INDEX]}. deplacer vos monde dans ${WORLDSTORAGE}."
exit 1
    fi
done
echo "lien verifie"
}

Fonction pour la mise en RAM :
Code:
to_ram() {
get_worlds
for INDEX in ${!WORLDNAME[@]}
do
if ${WORLDRAM[$INDEX]}
then
if [ -L $MCPATH/${WORLDNAME[$INDEX]} ]
then
as_user "rsync -rt --exclude 'ramdisk' ${WORLDSTORAGE}/${WORLDNAME[$INDEX]}/ $RAMDISK/${WORLDNAME[$INDEX]}"
echo "${WORLDNAME[$INDEX]} copie dans la ram"
fi
fi
done
}

Fonction pour la mise sur disque
Code:
to_disk() {
get_worlds
for INDEX in ${!WORLDNAME[@]}
do
as_user "rsync -rt --exclude 'ramdisk' $MCPATH/${WORLDNAME[$INDEX]}/ ${WORLDSTORAGE}/${WORLDNAME[$INDEX]}"
echo "${WORLDNAME[$INDEX]} copie sur le disque dur"
done
}

Fonction pour la mise a jour en mode feignant : (a ne pas mettre ne place pour le moment je dois corriger des choses dessus et je ne suis pas devant mon serveur)
Code:
mc_update() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
    then
        echo "$SERVICE est demarre, impossible de mettre a jour"
    else
        echo "Mise a jour de craftbukkit...."
    as_user "cd $MCPATH && wget -q -O $MCPATH/craftbukkit.jar.update http://ci.bukkit.org/job/dev-CraftBukkit/promotion/latest/Recommended/artifact/target/craftbukkit-0.0.1-SNAPSHOT.jar"
if [ -f $MCPATH/craftbukkit.jar.update ]
    then
        if `diff $MCPATH/craftbukkit-0.0.1-SNAPSHOT.jar $MCPATH/craftbukkit.jar.update > /dev/null`
    then
        echo "Vous utilisez deja la derniere version de CraftBukkit."
        as_user "rm $MCPATH/craftbukkit.jar.update"
    else
        as_user "mv $MCPATH/craftbukkit.jar.update $MCPATH/craftbukkit-0.0.1-SNAPSHOT.jar"
    echo "CraftBukkit correctement mis a jour"
fi
    else
    echo "CraftBukkit ne peut etre mis a jour"
    fi
fi
}

Et pour finir :
Code:
case "$1" in
start)
check_links
to_ram
mc_start
;;
stop)
as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Serveur en cours d arret\"\015'"
mc_stop
to_disk
;;
restart)
as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Le serveur reboot dans 15 secondes.\"\015'"
mc_stop
to_disk
check_links
to_ram
mc_start
;;
backup)
# Backups world
as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Sauvegarde du world.\"\015'"
mc_saveoff
to_disk
mc_world_backup
mc_saveon
as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Sauvegarde complete.\"\015'"
;;
whole-backup)
# Backup everything
mc_whole_backup
;;
update)
#update minecraft_server.jar and craftbukkit.jar
as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Serveur mis a jours dans 15 secondes.\"\015'"
mc_stop
to_disk
mc_whole_backup
mc_update
check_links
mc_start
;;
to-disk)
mc_saveoff
to_disk
mc_saveon
;;
connected)
as_user "screen -p 0 -S $SCREEN -X eval 'stuff list\015'"
sleep 3s
tac $MCPATH/server.log | grep -m 1 "Connectes"
;;
log-roll)
as_user "screen -p 0 -S $SCREEN -X eval 'stuff \"say Reboot pour cause de maintenance dans 15 secondes.\"\015'"
mc_stop
log_roll
mc_start
;;
last)
echo Recently logged in users:
cat $MCPATH/server.log | awk '/entity|conn/ {sub(/lost/,"disconnected");print $1,$2,$4,$5}'
;;
status)
if ps ax | grep -v grep | grep -v -i SCREEN | grep $SERVICE > /dev/null
then
echo "$SERVICE est actif."
else
echo "$SERVICE est stoppe."
fi
;;
version)
echo Craftbukkit version `awk '/Craftbukkit/ {sub(/\)/, ""); print $12}' $MCPATH/server.log`
;;
links)
check_links
;;
ramdisk)
change_ramdisk_state $2
;;
worlds)
get_worlds
for INDEX in ${!WORLDNAME[@]}
do
if ${WORLDRAM[$INDEX]}
then
echo "${WORLDNAME[$INDEX]} (ramdisk)"
else
echo ${WORLDNAME[$INDEX]}
fi
done
;;
help)
echo "Usage: /etc/init.d/minecraft command"
echo
echo "start - Démarrage du serveur"
echo "stop - Arrêt du serveur"
echo "restart - Re-demarre le serveur"
echo "backup - Sauvegarde les worlds suivant la routine de script"
echo "whole-backup - Sauvegarde complète de votre serveur"
echo "update -Mise a jour de votre serveur"
echo "log-roll - Déplace et gzip vos log "
echo "to-disk - copies les world sur le disque"
echo "connected - liste les utilisateurs connectés"
echo "status - Statut du serveur"
echo "version - Renvoie la version de craftbukkit"
echo "links - Creation des liens de synchro entre la ram et les worlds"
echo "last - voir les derniers utilisateurs"
echo "worlds - Voir tout les worlds actif"
echo "ramdisk WORLD - Passe un world sur disque dur dans la ram"
;;
*)
echo "No such command see /etc/init.d/minecraft help"
exit 1
;;
esac

exit 0
EOF

Je finit de tester des maintenances et je mets les scripts, car la par exemple la RAM n'est pas mise à 0 donc il existe la possibilité d'avoir des erreurs
 
Processeurs

En 1.8 un serveur avec 60 joueurs, sa lag... regarder le core du proc.
Ceux qui disent non, peuvent lever la tête et regarder la lune :p ou le soleil faire des saccades...

DD

Le problème du DD arrive si vous avez plusieurs serveurs et/ou logblock, (je sais pu le nom de l'autre).
La grande taille d'une map, n'apporte rien de positif sur les performances du DD.

Les serveurs tiers, font des enregistrement sur le DD de manières différentes...
 
Il me semble qu'il y a déjà la partition de SWAP qui tient ce rôle. Si l'on veut augmenter la taille du SWAP, il suffit d'augmenter la taille de la partition.
 
Hummm, non , enfin si tu parles du SWAP de linux. Cette partition est faite pour absorber une partie de la RAM si elle est remplie. En fait ça fait l'opposé de la solution. Ça fait croire au système que ta partition SWAP est de la RAM, ici on fait l'inverse, on fait croire que la RAM est un disque dur. :)

Je continue le tuto logiquement ce soir. Je commencerais par mettre en place la solution et proposer quelque petite choses en plus, comme une sauvegarde sur FTP et j'en passe.

Là j'essaye de trouver comment partager des maps en direct sur plusieurs serveurs, Ou utiliser les ressources inutilisé d'un serveur pour les mettre a profil sur un autre en production, à distance bien entendu (réalisable car les connexions inter serveur sont bien plus performante qu'une connexion ADSL :p)
 
Oui, en effet, je viens de me rendre compte que j'ai dit n'importe quoi. L'inattention due à la fatigue peut-être. Merci de la précision.

Ça change quelque chose si le serveur tourne sur un SSD ? J'ai pas eu le temps de me renseigner sur les vitesses de transfert.
 
Si tu as un SSD, ca va pas changer grand chose :P on est presque à la même vitesse, enfin ça dépends du modèle mais dans l'ensemble, les SSD tourne un poil moins vite
 
Je viens de comprendre mon énormité :p !

Ça peut être assez sympa si on fait tourner le serveur sur un disque dur mécanique classique. Mais bon, il faut avoir assez de RAM histoire d'en laisser assez à l'OS et au processeur.
 
Rien ne remplace un SSD. Le ramdisk peut aider certain serveur, mais pas tous... 1er lien google... http://www.minecraftwiki.net/wiki/Tutorials/Ramdisk_enabled_server

Il faudra à un moment save la map sur le DD ... et la, c'est le drame ... freezeeee de 2, 3 secondes ?
Le ramdisk peut vous aider, mais pas forcément... Sa apporte aussi d'autres problèmes.
(du vécu)

A refaire, perso, je prendrais un serv moins puissant à trop lire de bêtises...
Avec les erreurs on apprend :)

Moi je veux un tuto de juju pour faire un beau worldpress ;)