IOException: Troppi file aperti
-
20-09-2019 - |
Domanda
Sto cercando di eseguire il debug di una perdita di descrittore di file in una webapp Java in esecuzione in Jetty 7.0.1 su Linux.
L'applicazione era stata felicemente in esecuzione per un mese o giù di lì quando le richieste hanno cominciato a fallire a causa di troppi file aperti , e Jetty doveva essere riavviato.
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)
In un primo momento ho pensato che il problema era con il codice che lancia il programma esterno, ma è usando commons-exec e non vedo nulla di male con esso:
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"));
}
}
file aperti quotazione sul server posso vedere un alto numero di 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
quando Molo inizia ci sono solo 10 FIFO, dopo un paio di giorni ci sono centinaia di loro.
Lo so che è un po 'vago, in questa fase, ma hai qualche suggerimento su dove cercare prossimo, o come ottenere informazioni più dettagliate su tali descrittori di file?
Soluzione
Il tuo programma esterno non si comporta correttamente. Date un'occhiata al motivo per cui non lo fa.
Altri suggerimenti
Il problema deriva dal l'applicazione Java (o una libreria che si sta utilizzando).
prima , si dovrebbe leggere l'intero uscite (Google per StreamGobbler), e pronto!
Javadoc dice:
Il processo genitore usa questi flussi per alimentare ingresso e uscita da ottenere il sottoprocesso. Poiché alcuni nativo piattaforme forniscono solo buffer limitato formato per input e output standard corsi d'acqua, il mancato scrivere tempestivamente il flusso in entrata o leggere il flusso in uscita del sottoprocesso può causare sottoprocesso per bloccare, e persino situazione di stallo.
In secondo luogo , waitFor()
il processo per terminare.
È quindi dovrebbe chiudere i flussi di input, output e di errore.
Infine destroy()
Process.
Le mie fonti:
Come si esegue su Linux ho il sospetto che si è a corto di descrittori di file. Scopri ulimit. Ecco un articolo che descrive il problema: http : //www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/
Non si conosce la natura della vostra applicazione, ma ho visto questo errore si manifesta più volte a causa di una perdita di pool di connessioni, in modo che sarebbe la pena di verificare. Su Linux, le connessioni socket consumano i descrittori di file e file del file system. Solo un pensiero.
Oltre a guardare in questioni come la causa principale di perdite di file, ecc, al fine di fare un aumento di legittima i "file aperti" limite ed avere che persistono dopo il riavvio, prendere in considerazione la modifica
/etc/security/limits.conf
con l'aggiunta di qualcosa di simile
jetty soft nofile 2048
jetty hard nofile 4096
dove "pontile" è il nome utente in questo caso. Per maggiori dettagli su limits.conf, vedi http://linux.die.net/man /5/limits.conf
disconnettersi e quindi accedere di nuovo ed eseguire
ulimit -n
per verificare che il cambiamento è avvenuto. Nuovi processi di questo utente dovrebbero ora rispettare questo cambiamento. Questo link sembra descrivere come applicare il limite di processi già avviato ma io non hanno provato.
Il limite predefinito 1024 può essere troppo bassa per le grandi applicazioni Java.
È possibile gestire i FDS da soli. L'exec in Java restituisce un oggetto processo. A intermittenza verificare se il processo è ancora in esecuzione. Una volta completato chiudi i processi flussi STDERR, STDIN e STDOUT (ad esempio proc.getErrorStream.close ()). Che attenuare le perdite.
Questo problema viene quando si sta scrivendo i dati in molti file contemporaneamente e il sistema operativo dispone un limite fisso di file aperti. In Linux, è possibile aumentare il limite di file aperti.
https://www.tecmint.com/ aumentare-set-open-file-limiti-in-linux /
Come faccio a cambiare la numero di file aperti limita in Linux?