IOException: trop de fichiers ouverts

j'essaie de déboguer une fuite de descripteur de fichier dans une webapp Java tournant dans Jetty 7.0.1 sous Linux.

l'application fonctionnait bien depuis un mois environ lorsque les requêtes ont commencé à échouer à cause de trop de fichiers ouverts , et Jetty a dû être redémarré.

java.io.IOException: Cannot run program [external program]: java.io.IOException: error=24, Too many open files
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
    at java.lang.Runtime.exec(Runtime.java:593)
    at org.apache.commons.exec.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58)
    at org.apache.commons.exec.DefaultExecutor.launch(DefaultExecutor.java:246)

j'ai d'abord pensé que le problème était avec le code qui lance le programme externe, mais il utilise commons-exec et je ne vois pas tout ce qui ne va pas avec:

CommandLine command = new CommandLine("/path/to/command")
    .addArgument("...");
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();
Executor executor = new DefaultExecutor();
executor.setWatchdog(new ExecuteWatchdog(PROCESS_TIMEOUT));
executor.setStreamHandler(new PumpStreamHandler(null, errorBuffer));
try {
    executor.execute(command);
} catch (ExecuteException executeException) {
    if (executeException.getExitValue() == EXIT_CODE_TIMEOUT) {
        throw new MyCommandException("timeout");
    } else {
        throw new MyCommandException(errorBuffer.toString("UTF-8"));
    }
}

Liste des fichiers ouverts sur le serveur, je peut voir un grand nombre de mémoires Fifo:

# lsof -u jetty
...
java    524 jetty  218w  FIFO        0,6      0t0 19404236 pipe
java    524 jetty  219r  FIFO        0,6      0t0 19404008 pipe
java    524 jetty  220r  FIFO        0,6      0t0 19404237 pipe
java    524 jetty  222r  FIFO        0,6      0t0 19404238 pipe

quand Jetty commence il n'y a que 10 FIFOs, après quelques jours il y en a des centaines.

je sais que c'est un peu vague à ce stade, mais avez-vous des suggestions sur où regarder ensuite, ou comment obtenir des informations plus détaillées sur ces descripteurs de fichiers?

25
demandé sur Mirko N. 2010-01-11 23:25:45

7 réponses

Votre programme externe ne se comporte pas correctement. Jetez un oeil à pourquoi il ne le fait pas.

7
répondu Thorbjørn Ravn Andersen 2010-01-11 20:35:08

le problème vient de votre application Java (ou d'une bibliothèque que vous utilisez).

premier , vous devez lire l'ensemble des sorties (Google pour StreamGobbler), et pronto!

Javadoc dit:

le processus parent utilise ces flux pour alimenter les entrées et les sorties le processus secondaire. Parce que certains autochtones les plates-formes offrent peu de tampon taille pour entrée et sortie standard les flux, à défaut d'écrire rapidement le flux d'entrée ou lecture du flux de sortie de la sous-processus peut entraîner la sous-processus à bloc, et même de impasse.

second , waitFor() votre processus de résiliation. Vous devez alors fermer les flux input, output et error.

enfin destroy() votre Processus.

mes sources:

23
répondu ofavre 2011-05-11 12:22:42

comme vous utilisez Linux, je soupçonne que vous êtes à court de descripteurs de fichiers. Découvrez ulimit. Voici un article qui décrit le problème: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

8
répondu Greg Smith 2010-01-11 20:38:24

Je ne sais pas la nature de votre application, mais j'ai vu cette erreur se manifester plusieurs fois en raison d'une fuite de piscine de connexion, de sorte que cela vaudrait la peine de vérifier. Sous Linux, les connexions socket consomment des descripteurs de fichiers ainsi que des fichiers système de fichiers. Juste une pensée.

5
répondu alasdairg 2010-01-11 20:53:40

mis à part le fait d'examiner les causes profondes de problèmes tels que les fuites de fichiers, etc. afin de faire une augmentation légitime de la limite des "fichiers ouverts" et avoir qui persistent à travers les redémarrages, envisager l'édition

/etc/security/limits.conf

en ajoutant quelque chose comme ceci

jetty soft nofile 2048
jetty hard nofile 4096

où "jetty" est le nom d'utilisateur dans ce cas. Pour plus de détails sur les limites.conf, voir http://linux.die.net/man/5/limits.conf

déconnecter et puis se connecter à nouveau et exécuter

ulimit -n

pour vérifier que le changement a eu lieu. Les nouveaux processus de cet utilisateur doivent maintenant se conformer à ce changement. ce lien semble décrire comment appliquer la limite sur les processus déjà en cours, mais je ne l'ai pas essayé.

la limite par défaut 1024 peut être trop basse pour les grandes applications Java.

5
répondu Rami Jaamour 2017-03-20 10:18:27

, Vous pouvez gérer les fds vous-même. L'exec en java renvoie un objet Process. Vérifiez par intermittence si le processus est toujours en cours. Une fois qu'il a terminé fermer les processus stderr, STDIN, et STDOUT flux (par exemple proc.getErrorStream.proche.))( Qui permettront d'atténuer les fuites.

2
répondu allenjsomb 2011-03-24 13:24:49

ce problème vient lorsque vous écrivez des données dans de nombreux fichiers simultanément et votre système d'exploitation a une limite fixe de fichiers ouverts. Sous Linux, vous pouvez augmenter la limite des fichiers ouverts.

https://www.tecmint.com/increase-set-open-file-limits-in-linux /

Comment puis-je changer la limite du nombre de fichiers ouverts sous Linux?

1
répondu Vpn_talent 2018-06-06 12:43:07