노드 및 오류: EMFILE, 열려 있는 파일이 너무 많습니다.
며칠 동안 나는 오류에 대한 유효한 해결책을 찾아다녔다.
오류: EMFILE, 열려 있는 파일이 너무 많습니다.
많은 사람들이 같은 문제를 가지고 있는 것 같아요.통상적인 대답은 파일 기술자의 수를 늘리는 것입니다.그래서 제가 해봤어요
sysctl -w kern.maxfiles=20480
기본값은 10240 입니다.제가 디렉토리에서 취급하고 있는 파일의 수가 10240 미만이기 때문에, 이것은 조금 이상합니다.파일 기술자 수를 늘린 후에도 여전히 동일한 오류가 발생합니다.
두 번째 질문:
몇 번이나 검색한 결과, 「열린 파일이 너무 많다」라고 하는 문제의 회피책을 발견했습니다.
var requestBatches = {};
function batchingReadFile(filename, callback) {
// First check to see if there is already a batch
if (requestBatches.hasOwnProperty(filename)) {
requestBatches[filename].push(callback);
return;
}
// Otherwise start a new one and make a real request
var batch = requestBatches[filename] = [callback];
FS.readFile(filename, onRealRead);
// Flush out the batch on complete
function onRealRead() {
delete requestBatches[filename];
for (var i = 0, l = batch.length; i < l; i++) {
batch[i].apply(null, arguments);
}
}
}
function printFile(file){
console.log(file);
}
dir = "/Users/xaver/Downloads/xaver/xxx/xxx/"
var files = fs.readdirSync(dir);
for (i in files){
filename = dir + files[i];
console.log(filename);
batchingReadFile(filename, printFile);
유감스럽게도 같은 에러가 계속 발생하고 있습니다.이 코드에 무슨 문제가 있나요?
graceful-fs가 작동하지 않을 때...아니면 누출이 어디서 발생하는지 알고 싶을 수도 있어요이 프로세스를 수행합니다.
(예를 들어 소켓에 문제가 있는 경우 graceful-fs는 왜건을 수리하지 않습니다.)
내 블로그 기사: http://www.blakerobertson.com/devlog/2014/1/11/how-to-determine-whats-causing-error-connect-emfile-nodejs.html
분리 방법
이 명령어는 nodejs 프로세스의 열린 핸들 수를 출력합니다.
lsof -i -n -P | grep nodejs
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
nodejs 12211 root 1012u IPv4 151317015 0t0 TCP 10.101.42.209:40371->54.236.3.170:80 (ESTABLISHED)
nodejs 12211 root 1013u IPv4 151279902 0t0 TCP 10.101.42.209:43656->54.236.3.172:80 (ESTABLISHED)
nodejs 12211 root 1014u IPv4 151317016 0t0 TCP 10.101.42.209:34450->54.236.3.168:80 (ESTABLISHED)
nodejs 12211 root 1015u IPv4 151289728 0t0 TCP 10.101.42.209:52691->54.236.3.173:80 (ESTABLISHED)
nodejs 12211 root 1016u IPv4 151305607 0t0 TCP 10.101.42.209:47707->54.236.3.172:80 (ESTABLISHED)
nodejs 12211 root 1017u IPv4 151289730 0t0 TCP 10.101.42.209:45423->54.236.3.171:80 (ESTABLISHED)
nodejs 12211 root 1018u IPv4 151289731 0t0 TCP 10.101.42.209:36090->54.236.3.170:80 (ESTABLISHED)
nodejs 12211 root 1019u IPv4 151314874 0t0 TCP 10.101.42.209:49176->54.236.3.172:80 (ESTABLISHED)
nodejs 12211 root 1020u IPv4 151289768 0t0 TCP 10.101.42.209:45427->54.236.3.171:80 (ESTABLISHED)
nodejs 12211 root 1021u IPv4 151289769 0t0 TCP 10.101.42.209:36094->54.236.3.170:80 (ESTABLISHED)
nodejs 12211 root 1022u IPv4 151279903 0t0 TCP 10.101.42.209:43836->54.236.3.171:80 (ESTABLISHED)
nodejs 12211 root 1023u IPv4 151281403 0t0 TCP 10.101.42.209:43930->54.236.3.172:80 (ESTABLISHED)
....
1023u(마지막 줄)는 기본 최대값인 1024번째 파일 핸들입니다.
자, 이제 마지막 칸을 보세요.열려 있는 리소스가 표시됩니다.같은 자원명을 가지는 행이 다수 표시됩니다.이제 코드 어디쯤에서 누출을 찾아야 하는지 알 수 있길 바랍니다.
여러 노드 프로세스를 모를 경우 먼저 pid 12211을 가진 프로세스를 검색합니다.그러면 절차가 설명됩니다.
상기의 경우, 매우 유사한 IP 주소가 다수 있는 것을 알 수 있었습니다.그들은 모두54.236.3.###
lookup을 제referenced.ip address lookup으로 판정할 수 있었습니다.
명령어 레퍼런스
이 구문을 사용하여 프로세스가 열려 있는 핸들의 수를 결정합니다.
특정 pid에 대해 열려 있는 파일 수를 가져오려면 다음과 같이 하십시오.
이 명령어를 사용하여 앱에서 다양한 이벤트를 수행한 후 열린 파일 수를 테스트했습니다.
lsof -i -n -P | grep "8465" | wc -l
# lsof -i -n -P | grep "nodejs.*8465" | wc -l
28
# lsof -i -n -P | grep "nodejs.*8465" | wc -l
31
# lsof -i -n -P | grep "nodejs.*8465" | wc -l
34
프로세스 제한은 어느 정도입니까?
ulimit -a
원하는 선은 다음과 같습니다.
open files (-n) 1024
제한을 영구적으로 변경합니다.
- Ubuntu 14.04에서 테스트 완료, nodejs v.7.9
많은 연결을 열 것으로 예상되는 경우(웹소켓이 좋은 예입니다), 제한을 영구적으로 늘릴 수 있습니다.
파일: /etc/common.d/common-common(마지막에 추가)
session required pam_limits.so
파일: /etc/security/security.conf(마지막에 추가하거나 이미 있는 경우 편집)
root soft nofile 40000 root hard nofile 100000
nodejs를 재시작하고 ssh에서 로그아웃/로그아웃합니다.
이전 노드에서는 작동하지 않을 수 있습니다.JS 서버를 재시작해야 합니다.
노드가 다른 uid로 실행되는 경우 대신 사용합니다.
Isaac Schlueter(node.js 유지관리자)의 모듈을 사용하는 것이 가장 적합한 솔루션일 것입니다.EMFILE이 검출되면 증분 백오프가 실행됩니다.빌트인의 드롭인 대체품으로 사용할 수 있습니다.fs
★★★★★★ 。
이것이 도움이 될지는 모르겠지만, 저는 의존관계가 많은 큰 프로젝트를 시작했기 때문에 같은 오류를 던졌습니다.했습니다.watchman
을 사용하다
brew update
brew install watchman
2019년 6월 26일 편집 : Watchman에 대한 Github 링크
같은 문제로 위 사항을 모두 수행했지만 아무런 효과가 없었습니다.밑에서 100% 작동했어간단한 설정 변경
옵션 1: 제한 설정(대부분 작동하지 않음)
user@ubuntu:~$ ulimit -n 65535
전류 한계 점검
user@ubuntu:~$ ulimit -n
1024
옵션 2: 사용 가능한 제한을 65535로 늘립니다.
user@ubuntu:~$ sudo nano /etc/sysctl.conf
여기에 다음 행을 추가합니다.
fs.file-max = 65535
새 구성으로 새로 고치려면 이 작업을 수행합니다.
user@ubuntu:~$ sudo sysctl -p
다음 파일 편집
user@ubuntu:~$ sudo vim /etc/security/limits.conf
여기에 다음 행을 추가합니다.
root soft nproc 65535
root hard nproc 65535
root soft nofile 65535
root hard nofile 65535
다음 파일 편집
user@ubuntu:~$ sudo vim /etc/pam.d/common-session
이 행을 추가합니다.
session required pam_limits.so
로그아웃 및 로그인 후 다음 명령을 사용해 보십시오.
user@ubuntu:~$ ulimit -n
65535
옵션 3: 이 행을 추가합니다.
DefaultLimitNOFILE=65535
로로 합니다./etc/systemd/system.conf
★★★★★★★★★★★★★★★★★」/etc/systemd/user.conf
저는 오늘 이 문제에 부딪혔고, 이에 대한 좋은 해결책을 찾지 못해 이 문제에 대처하기 위한 모듈을 만들었습니다.@fbartho의 스니펫에서 영감을 받았지만 fs 모듈을 덮어쓰지 않도록 하고 싶었습니다.
제가 쓴 모듈은 Filequeue로 fs와 같이 사용합니다.
var Filequeue = require('filequeue');
var fq = new Filequeue(200); // max number of files to open at once
fq.readdir('/Users/xaver/Downloads/xaver/xxx/xxx/', function(err, files) {
if(err) {
throw err;
}
files.forEach(function(file) {
fq.readFile('/Users/xaver/Downloads/xaver/xxx/xxx/' + file, function(err, data) {
// do something here
}
});
});
파일을 너무 많이 읽고 있습니다.노드가 파일을 비동기적으로 읽습니다. 모든 파일을 한 번에 읽습니다.10240 한계치를 읽고 있을 겁니다.
이것이 기능하는지 확인합니다.
var fs = require('fs')
var events = require('events')
var util = require('util')
var path = require('path')
var FsPool = module.exports = function(dir) {
events.EventEmitter.call(this)
this.dir = dir;
this.files = [];
this.active = [];
this.threads = 1;
this.on('run', this.runQuta.bind(this))
};
// So will act like an event emitter
util.inherits(FsPool, events.EventEmitter);
FsPool.prototype.runQuta = function() {
if(this.files.length === 0 && this.active.length === 0) {
return this.emit('done');
}
if(this.active.length < this.threads) {
var name = this.files.shift()
this.active.push(name)
var fileName = path.join(this.dir, name);
var self = this;
fs.stat(fileName, function(err, stats) {
if(err)
throw err;
if(stats.isFile()) {
fs.readFile(fileName, function(err, data) {
if(err)
throw err;
self.active.splice(self.active.indexOf(name), 1)
self.emit('file', name, data);
self.emit('run');
});
} else {
self.active.splice(self.active.indexOf(name), 1)
self.emit('dir', name);
self.emit('run');
}
});
}
return this
};
FsPool.prototype.init = function() {
var dir = this.dir;
var self = this;
fs.readdir(dir, function(err, files) {
if(err)
throw err;
self.files = files
self.emit('run');
})
return this
};
var fsPool = new FsPool(__dirname)
fsPool.on('file', function(fileName, fileData) {
console.log('file name: ' + fileName)
console.log('file data: ', fileData.toString('utf8'))
})
fsPool.on('dir', function(dirName) {
console.log('dir name: ' + dirName)
})
fsPool.on('done', function() {
console.log('done')
});
fsPool.init()
우리 모두와 마찬가지로 당신도 비동기 I/O의 또 다른 피해자입니다.비동기 호출에서는 많은 파일을 루프하면 Node.js는 읽을 각 파일의 파일 기술자를 열고 닫을 때까지 처리를 기다립니다.
파일 기술자는 서버에서 읽을 수 있는 리소스를 사용할 수 있을 때까지 열려 있습니다.파일이 작고 읽기 또는 업데이트가 빠르더라도 시간이 걸리지만 동시에 루프가 중단되지 않고 새 파일 설명자가 열립니다.따라서 파일이 너무 많으면 곧 제한에 도달하여 아름다운 EMFILE을 얻을 수 있습니다.
이 영향을 피하기 위해 큐를 작성하는 방법이 하나 있습니다.
Async를 써주신 분들 덕분에 매우 유용한 기능이 있습니다.Async라는 방법이 있습니다.queue는 제한이 있는 새 큐를 작성한 후 파일 이름을 큐에 추가합니다.
주의: 많은 파일을 열어야 하는 경우 현재 열려 있는 파일을 저장하고 무한히 다시 열지 않는 것이 좋습니다.
const fs = require('fs')
const async = require("async")
var q = async.queue(function(task, callback) {
console.log(task.filename);
fs.readFile(task.filename,"utf-8",function (err, data_read) {
callback(err,task.filename,data_read);
}
);
}, 4);
var files = [1,2,3,4,5,6,7,8,9,10]
for (var file in files) {
q.push({filename:file+".txt"}, function (err,filename,res) {
console.log(filename + " read");
});
}
각 파일이 큐(console.log 파일명)에 추가되는 것은 알 수 있지만, 현재 큐가 이전에 설정한 제한을 밑돌고 있는 경우에만 알 수 있습니다.
async.syslog는 콜백을 통해 큐의 가용성에 대한 정보를 가져옵니다.이 콜백은 데이터 파일이 읽혀지고 액션이 수행되었을 때만 호출됩니다.(fileRead 메서드 참조)
따라서 파일 설명자에 압도되어서는 안 됩니다.
> node ./queue.js
0.txt
1.txt
2.txt
0.txt read
3.txt
3.txt read
4.txt
2.txt read
5.txt
4.txt read
6.txt
5.txt read
7.txt
1.txt read (biggest file than other)
8.txt
6.txt read
9.txt
7.txt read
8.txt read
9.txt read
이 문제를 해결하기 위해 코드 조각 작성을 마쳤습니다. 다른 모든 솔루션은 너무 무거워 보여 프로그램 구조를 변경해야 합니다.
이 솔루션은 fs.readFile 또는 fs.writeFile 콜을 모두 정지시키기 때문에 항상 설정된 수보다 많은 콜이 전송되지 않습니다.
// Queuing reads and writes, so your nodejs script doesn't overwhelm system limits catastrophically
global.maxFilesInFlight = 100; // Set this value to some number safeish for your system
var origRead = fs.readFile;
var origWrite = fs.writeFile;
var activeCount = 0;
var pending = [];
var wrapCallback = function(cb){
return function(){
activeCount--;
cb.apply(this,Array.prototype.slice.call(arguments));
if (activeCount < global.maxFilesInFlight && pending.length){
console.log("Processing Pending read/write");
pending.shift()();
}
};
};
fs.readFile = function(){
var args = Array.prototype.slice.call(arguments);
if (activeCount < global.maxFilesInFlight){
if (args[1] instanceof Function){
args[1] = wrapCallback(args[1]);
} else if (args[2] instanceof Function) {
args[2] = wrapCallback(args[2]);
}
activeCount++;
origRead.apply(fs,args);
} else {
console.log("Delaying read:",args[0]);
pending.push(function(){
fs.readFile.apply(fs,args);
});
}
};
fs.writeFile = function(){
var args = Array.prototype.slice.call(arguments);
if (activeCount < global.maxFilesInFlight){
if (args[1] instanceof Function){
args[1] = wrapCallback(args[1]);
} else if (args[2] instanceof Function) {
args[2] = wrapCallback(args[2]);
}
activeCount++;
origWrite.apply(fs,args);
} else {
console.log("Delaying write:",args[0]);
pending.push(function(){
fs.writeFile.apply(fs,args);
});
}
};
백파이프는 거스름돈만 있으면 됩니다.
FS.readFile(filename, onRealRead);
=>
var bagpipe = new Bagpipe(10);
bagpipe.push(FS.readFile, filename, onRealRead))
백파이프를 사용하면 평행선을 제한할 수 있습니다.자세한 내용은 https://github.com/JacksonTian/bagpipe를 참조해 주세요.
nodemon 명령어 실행 시 동일한 문제가 발생하여 숭고한 텍스트로 열려 있는 파일 이름을 줄이자 오류가 사라졌습니다.
cwait는 약속을 반환하는 함수의 동시 실행을 제한하기 위한 일반적인 솔루션입니다.
이 경우 코드는 다음과 같습니다.
var Promise = require('bluebird');
var cwait = require('cwait');
// Allow max. 10 concurrent file reads.
var queue = new cwait.TaskQueue(Promise, 10);
var read = queue.wrap(Promise.promisify(batchingReadFile));
Promise.map(files, function(filename) {
console.log(filename);
return(read(filename));
})
@blak3r의 답변을 바탕으로 다른 진단에 도움이 될 경우에 사용하는 간단한 정보를 소개합니다.
한 Node 다음 행에서 Node.js의 할 수 .lsof
이치노
openFiles = child_process.execSync(`lsof -p ${process.pid}`);
됩니다.lsof
현재 실행 중인 Node.js 프로세스에 의해 필터링되고 버퍼를 통해 결과를 반환합니다.
'아예'를 사용합니다.console.log(openFiles.toString())
버퍼를 문자열로 변환하고 결과를 기록합니다.
nodemon 사용자: --ignore 플래그를 사용하여 문제를 해결합니다.
예:
nodemon app.js --ignore node_modules/ --ignore data/
의 「」를 합니다.fs-extra
.
는 그 를 는나에 있었다.Ubuntu
( 및 파일: (16 18 18))이 경우, (16 18 18)가 있다lsof |wc -l
) 。fs-extra
」8.1.0
로 된 후9.0.0
"Error: EMFILE, too many open files" (오류: EMFILE, 열려 있는 파일이 너무 많습니다.)
노드 처리 파일 시스템에서 다양한 OS에서 다양한 문제를 경험했습니다.파일 시스템은 분명 사소한 것이 아닙니다.
워치맨 설치, 제한 변경 등을 했는데 Gulp에서는 작동하지 않았습니다.
iterm2를 재기동하면 실제로 도움이 됩니다.
아직 솔루션을 찾고 있는 사람에게는 비동기 대기를 사용하는 것이 좋습니다.
fs.readdir(<directory path></directory>, async (err, filenames) => {
if (err) {
console.log(err);
}
try {
for (let filename of filenames) {
const fileContent = await new Promise((resolve, reject) => {
fs.readFile(<dirctory path + filename>, 'utf-8', (err, content) => {
if (err) {
reject(err);
}
resolve(content);
});
});
... // do things with fileContent
}
} catch (err) {
console.log(err);
}
});
제 의견은 이렇습니다.CSV 파일은 텍스트 행에 불과하다고 생각하기 때문에 이 문제를 피하기 위해 데이터(스트링)를 스트리밍했습니다.
내 사용 사례에 맞는 가장 쉬운 솔루션.
그레이스 풀 fs 또는 표준 fs와 함께 사용할 수 있습니다.작성할 때 파일에 헤더는 없습니다.
// import graceful-fs or normal fs
const fs = require("graceful-fs"); // or use: const fs = require("fs")
// Create output file and set it up to receive streamed data
// Flag is to say "append" so that data can be recursively added to the same file
let fakeCSV = fs.createWriteStream("./output/document.csv", {
flags: "a",
});
그리고 이렇게 한 파일로 스트리밍해야 하는 데이터는
// create custom streamer that can be invoked when needed
const customStreamer = (dataToWrite) => {
fakeCSV.write(dataToWrite + "\n");
};
data To Write는 단순히 ";" 또는 ""와 같은 커스텀 구분자를 가진 문자열입니다.
const dataToWrite = "batman" + ";" + "superman"
customStreamer(dataToWrite);
이것은 파일에 "batman; superman"이라고 씁니다.
- 이 예에서는 에러 캐치등의 문제는 발생하지 않습니다.
- 문서: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options
이렇게 하면 Visual Studio 템플릿(web.config)을 사용하여 생성된 React 솔루션을 배포하는 데 어려움을 겪고 있는 경우 문제가 해결될 수 있습니다.Azure 릴리스 파이프라인에서 템플릿을 선택할 때 다음을 사용합니다.
Azure App Service 도입
대신:
Node.js 앱을 Azure App Service에 배포합니다.
나한텐 효과가 있었어!
지금까지 어떤 답변에서도 고려되거나 논의되지 않은 또 다른 가능성이 있습니다. 바로 심볼릭 링크 사이클입니다.
노드의 재귀 파일 시스템 감시기가 심볼 링크의 주기를 탐지하고 처리하지 않는 것 같습니다. 이 에러로 수 .nfiles
실행만으로 ulimit:
mkdir a
mkdir a/b
cd a/b
ln -s .. c
GNUfind
는 심볼링크 사이클을 인식하고 중단합니다.
$ find a -follow
a
a/b
find: File system loop detected; ‘a/b/c’ is part of the same file system loop as ‘a’.
노드는 그렇지 않습니다.나무 위에 시계를 세우면, 그 시계에서 뿜어져 나올 거예요.EMFILE, too many open files
에러입니다.
이 일이 일어날 수 있는 다른 일들 중에서node_modules
억제 관계가 있는 경우:
parent/
package.json
child/
package.json
제가 만들려던 프로젝트에서 우연히 발견하게 된 거죠
이 문제를 너무 복잡하게 만들 필요는 없습니다.다시 시도해도 문제 없습니다.
import { promises as fs } from "fs";
const filepaths = [];
const errors = [];
function process_file(content: string) {
// logic here
}
await Promise.all(
filepaths.map(function read_each(filepath) {
return fs
.readFile(filepath, "utf8")
.then(process_file)
.catch(function (error) {
if (error.code === "EMFILE") return read_each(filepath);
else errors.push({ file: filepath, error });
});
}),
);
Windows 에서는, 다음과 같이 되어 있지 않은 것 같습니다.ulimit
명령어를 사용하여 열려 있는 파일 수를 늘립니다.인graceful-fs
큐를 유지하여 I/O 작업을 수행합니다(예: 파일 읽기/쓰기).
하지만,fs.readFile, fs.writeFile
에 기초하고 있다.fs.open
따라서 이 오류를 해결하려면 수동으로 파일을 열거나 닫아야 합니다.
import fs from 'fs/promises';
const fd = await fs.open('path-to-file', 'r');
await fd.readFile('utf-8'); // <== read through file handle
await fd.close(); // <== manually close it
나는 이 문제가 있었고, 나는 그것을 실행함으로써 해결했다.npm update
그리고 그것은 성공하였다.
경우에 따라 node_modules를 삭제해야 할 수 있습니다.rm -rf node_modules/
노드 버전 ERR emfile을 너무 많은 열린 파일로 변경하면 이 문제가 발생할 수 있습니다.
- 컴퓨터를 재기동합니다.
- 양조 설치 감시원
그것은 문제를 완전히 고쳐야 한다.
먼저 다음을 사용하여 엑스포 버전을 업데이트하십시오.expo update
그리고 나서 달려라yarn / npm install
이것으로 문제가 해결되었습니다!
언급URL : https://stackoverflow.com/questions/8965606/node-and-error-emfile-too-many-open-files
'source' 카테고리의 다른 글
출력으로 Python 버전 인쇄 중 (0) | 2022.11.19 |
---|---|
precedence 및 비트마스크 (0) | 2022.11.19 |
sklearn을 사용하여 데이터 프레임 열 확장 (0) | 2022.11.19 |
MyISAM 레코드가 3억 5천만 개 이상인 25GB의 대용량 테이블을 업데이트하려면 어떻게 해야 합니까? (0) | 2022.11.19 |
이름이 같은 두 클래스를 가져오는 중입니다.어떻게 대처해야 할까? (0) | 2022.11.19 |