Publié le 31 Janvier 2013

Ce matin j'ai rencontré l'erreur "Too many open files" sur une machine de prod :(

Déjà première chose à vérifier: le nombre max de fichiers ouvrables simultanéments.

Cette info se trouve dans /proc

# cat /proc/sys/fs/file-max
352772

Ensuite il faut récupérer le PID du process et vérifier les fichiers ouvert:

 # lsof -p <PID>
COMMAND  PID   USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
java    3200 patatos  cwd    DIR                8,7    12288 8388609 /home/patatos
java    3200 patatos  rtd    DIR                8,1     4096       2 /
java    3200 patatos  txt    REG                8,6     7750 2228272 /usr/local/prog/jdk1.7.0_07/bin/java
java    3200 patatos  mem    REG                8,1    31128  660135 /lib/x86_64-linux-gnu/libnss_dns-2.15.so
...

pour compter le nombre de fichier il suffit de compter le nombre de lignes (-1 pour l'entête)

# lsof -p <PID> | wc -l
187 

Voir les commentaires

Rédigé par Bliz

Publié dans #Linux

Repost 0

Publié le 22 Janvier 2013

On peut récupére la version de MySQL avec la commande suivante:

mysql> SHOW VARIABLES LIKE "%version%";

Ce qui donne:

+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| protocol_version        | 10                           |
| version                 | 5.1.40                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | unknown-linux-gnu            |
+-------------------------+------------------------------+

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 16 Janvier 2013

Voilà un pattern que je rencontre dans notre codebase actuel. Il s'agit d'utiliser une interface java pour y définir des constantes.

Par exemple:

public interface Constantes {

   public static final String MY_NAME = "my_name";
   // etc ...

Ensuite la classe qui utilise ces constantes implémente l'interface:

public class MaClasse implements Constantes {

   private String name = MY_NAME;
   // etc ...

En implémentant l'interface Constantes on peut utiliser directement le nom des constantes sans les préfixer par le nom de l'interface. C'est vrai ça fait plus clair dans le code car on gagne en lisibilité.

Cependant il y a quelques inconvénients qui peuvent faire perdre un temps fou en support (en débuggage quoi).

En fait les constantes sont héritées de l'interface (oui ça fait bizarre pour des champs static mais c'est bien le cas).

De plus si je déclare une constante MY_NAME dans MaClasse je vais masquer celle de l'interface:

public class MaClasse implements Constantes {

   private static final String MY_NAME = "ma_classe";

   private String name = MY_NAME;
   // etc ...

}

Maintenant name vaut "ma_classe" et non plus "my_name" comme défini dans l'interface.

Encore ici on a un lien direct avec l'interface mais ça peut être moins évident avec des sous-classes qui n'implémente pas l'interface directement. (Normalement l'IDE génère un warning en cas de masquage, mais bon).

En fait il existe un moyen plus sûr de faire la même chose. Au lieu d'utiliser une interface il faut mieux utiliser une classe non instanciable, puis utiliser un import static dans la classe qui utilise ces constantes: 

public final class Constantes {

   private Constantes(){
      throw new UnsupportedOperationException();
   }

   public static final String MY_NAME = "my_name";
   // etc ...

Ensuite dans la classe qui utilise les constantes:

import static mon.package.Constantes.*;

public class MaClass {

   private String name = MY_NAME;
   // etc ...

On garde la même lisibilité qu'avec l'interface et les constantes ne sont plus héritées ce qui évite le risque de confusion.

Voir les commentaires

Rédigé par Bliz

Publié dans #Java

Repost 0

Publié le 15 Janvier 2013

Voilà la situation:

J'ai un fichier archivé sous Git. Je travaille dessus et voilà je ne suis pas satisfait de mes modifs et je veux récupérer la version originale (celle avant que j'effectue mes modifs).

Et bien sous Git c'est très logique, il suffit d'extraire à nouveau le fichier depuis Git :

git checkout mon_dossier/mon_fichier

Voir les commentaires

Rédigé par Bliz

Publié dans #Version control

Repost 0

Publié le 10 Janvier 2013

Pour ceux qui utilise MySQL vous êtes certainement amené à travailler avec la ligne de commande MySQL.

Il y a une commande très utile pour logger les actions effectuées (par exemple lors d'une intervention en production):

mysql> tee mysql-cli.log

Et oui c'est analogue à la commande tee de linux/unix. Il suffit de préciser le fichier dans lequel logger les actions.

Attention tout ce qui est affiché dans la console est aussi loggé dans le fichier (les commandes tapées mais aussi les résultats obtenus).

Bien pratique lors des appels supports!

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 9 Janvier 2013

Sur mon projet nous utilisons xmlbeans pour générer des fichiers sources. Malheureusement ces fichiers ne sont pas générés dans target/generated-sources mais directement sous src/main/java (dans un package particulier bien sûr).

Il faut donc ajouter la suppression de ce répertoire à la phase de clean. Pour ceci il faut configurer le plugin maven-clean-plugin de la façon suivante:

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-clean-plugin</artifactId>
 <configuration>
  <filesets>
   <fileset>
    <directory>src/main/java/com/patatos/monpackage/</directory>
    <followSymlinks>false</followSymlinks>
    <excludes>
     <exclude>*.java</exclude>
    </excludes>
   </fileset>
  </filesets>
 </configuration>
</plugin>

Le bloc <excludes> est optionnel mais il permet de garder les classes se trouvant directement dans monpackage tout en supprimant tous les sous-packages. 

S'il est absent cela effacera directemet monpackage complet. Alternativement on pourrait utiliser un bloc <includes> pour ne spécifier que les fichiers à effacer.

Plus de détails sur la configuration des filesets sur la page du maven-clean-plugin.

Voir les commentaires

Rédigé par Bliz

Publié dans #Maven

Repost 0

Publié le 8 Janvier 2013

Dans une petite appli web, il y a un texte généré en PHP. Ce texte s'affiche dans un textarea ... jusque là, tout va bien.

C'est maintenant que Javascript entre en jeu. Selon certaines actions utilisateur il faut changer le contenu du textarea en utilisant Javascript, mais les textes sont toujours générés par PHP.

En gros c'est PHP qui génère du javascript. Il faut donc encoder le texte généré en PHP pour être utilisable en javascript.

Les 2 principaux problèmes que j'ai noté sont les ' et les \n qu'il faut protéger. Le code suivant fait l'affaire dans mon cas (attention ce n'est pas très propre et je ne pense pas que ça fonctionne dans tous les cas):

<?php
 echo 'var monTexte = "'.str_replace("\n", '\n', addslashes($mon_texte)).';';
?> 

Ce que fait cette ligne c'est protéger toutes quotes avec un \ puis remplacer les sauts de ligne par des \n.

ça a suffit dans mon cas. J'ai vu des solutions qui utilisaient json_encode() mais je n'ai pas réussi à le faire marcher dans mon cas (même en convertissant le texte un utf8 avec utf8_encode() auparavant).

Si vous avez d'autres idées, je suis preneur.

Voir les commentaires

Rédigé par Bliz

Publié dans #Php

Repost 0

Publié le 4 Janvier 2013

Quand je démarre XMind j'obtiens le message d'erreur suivant:

An error has occured.. See the log file
/home/bliz/configuration/1357288023946.log

Et voici le contenu du fichier de log en question:

 !SESSION 2013-01-04 09:27:03.687 -----------------------------------------------
eclipse.buildId=unknown
java.version=1.7.0_07
java.vendor=Oracle Corporation
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US
Framework arguments:  -product org.xmind.cathy.product
Command-line arguments:  -os linux -ws gtk -arch x86_64 -product org.xmind.cathy.product -data ../Commons/data/workspace-cathy

!ENTRY org.eclipse.osgi 4 0 2013-01-04 09:27:04.242
!MESSAGE Application error
!STACK 1
java.lang.IllegalStateException: Unable to acquire application service. Ensure that the org.eclipse.core.runtime bundle is resolved and started (see config.ini).
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:74)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1386)

En fait ce qui pose problème ce sont tous les chemins relatifs qui se trouvent dans XMind.ini :

-product
org.xmind.cathy.product
-configuration
./configuration
-data
../Commons/data/workspace-cathy
-startup
../Commons/plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
../Commons/plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.100.v20110505
--launcher.defaultAction
openFile
-showsplash
org.xmind.cathy
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Dorg.xmind.product.distribution.id=cathy_portable

 

Il faut donc éditer ce fichier et remplacer tous les chemins relatifs par des chemins absolus.

Voir les commentaires

Rédigé par Bliz

Publié dans #Linux

Repost 0

Publié le 3 Janvier 2013

Allez une petite astuce sympa pour bien commencer l'année pour ceux qui utilisent la ligne de commande MySQL.

Si vous faites des SELECT et que le résultat retourné contient beaucoup de ligne c'est assez pénible dans un terminal (surtout si vous travailler sur une machine à distance).

Evidemment on peut toujours ajouté un LIMIT 50; à la fin de la requête mais bon ... on a vite fait d'en oublier un.

Totu ça pour dire qu'on peut utiliser la commande pager qui permet de spécifier une commande à utiliser lors de l'affichage des résultats.

Par exemple:

mysql> pager more
PAGER set to 'more'

Cette commande permet d'utiliser more lors de l'affichage des résultats et donc on aura qu'un écran d'afficher.

On peut également utiliser grep pour filtrer les lignes à afficher, etc ...

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0

Publié le 2 Janvier 2013

Aujourd'hui j'ai besoin de modifier une clé primaire sur une table, autrement dit de supprimer l'existante puis d'en créer une nouvelle.

Le problème il y a un auto_increment sur le champ de la clé primaire qui empêche la suppression de celle-ci.

mysql> alter table ma_table drop primary key;
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

Et là solution est assez simple : tout d'abord supprimer l'auto-increment puis ensuite la clé primaire.

Pour supprimer l'auto-increment il faut changer la définition du champ avec un alter table.

mysql> alter table ma_table modify old_id bigint(20) unsigned not null;
Query OK, 0 rows affected (0.12 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table ma_table drop primary key;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

 

Voir les commentaires

Rédigé par Bliz

Publié dans #MySQL

Repost 0