Node JS에서 "Tail -f"구현
4700 단어 linuxnodejavascriptwebdev
Linux는 현재까지 개발된 가장 아름다운 것 중 하나이며 때때로 "ls"가 배후에서 정확히 작동하는 방식과 같이 Linux의 특정 명령이 내부에서 어떻게 작동하는지 궁금합니다. 그래서 가장 많이 사용되는 리눅스 명령어 중 하나인 "Tail -f"를 nodejs에서 복제해 보았습니다.
모르시는 분들을 위해 "Tail -f"는 파일의 마지막 10줄을 인쇄한 다음 파일의 업데이트를 모니터링하고 파일이 업데이트될 때 내용을 인쇄합니다. 이제 노드 js에는 파일과 폴더를 가지고 노는 데 도움이 되는 내장 파일 시스템 모듈이 있으며 파일을 읽고, 파일에 모니터를 유지하고, 파일을 작성하는 데 사용할 수 있는 몇 가지 직접적인 방법이 있습니다. 따라서 이러한 명령을 취하여 차례로 사용하는 것이 쉬운 것처럼 들리지만 그렇게 쉽지는 않습니다.
우리가 처리해야 할 것들:
파일을 업데이트할 때마다 데이터를 가져와야 합니다.
파일이 업데이트될 때마다 전체 파일을 읽지 않았습니다.
그래서 nodejs의 fs 패키지에서 사용할 수 있는 모든 방법을 살펴보기 시작했습니다. 파일을 한 줄씩 읽고 각 줄에서 이벤트의 거짓말 데이터를 내보내는 readline이 있습니다.
// Read file line by line
var readline = require('readline');
var rl = readline.createInterface(process.stdin, process.stdout);
rl.on('line', (log) => {
console.log(`Log is: ${log}`);
rl.close();
});
이 방법은 내 경우에 매우 유용해 보였기 때문에 시작했지만 이제 이 방법을 호출해야 하는 시점을 결정해야 합니다. 업데이트를 위해 파일을 주시해야 하므로 파일의 변경 사항을 감지할 수 있는 다른 패키지를 찾았습니다.
파일이 변경될 때마다 이벤트를 내보내는 fs.watchfile이 있습니다. 이 메서드를 사용해 보았지만 이 메서드가 메타데이터 업데이트에 대한 이벤트를 내보내는 것을 알았으므로 일부 필터를 추가해야 합니다. 각 이벤트에 대한 현재 및 이전 통계를 얻었습니다. 이제 파일 크기를 비교하여 실제 데이터가 파일에서 업데이트되는지 여부를 확인하고 파일 크기가 변경된 경우에만 작업을 수행합니다.
// Keep a watch on file value change
fs.watchFile(filename, (curr, prev) => {
console.log("Previous Stats", prev);
console.log("Current Stats", curr);
if (curr.size.valueOf() === prev.size.valueOf())
return;
});
확실하게 하기 위해 향후 참조를 위해 현재 크기를 저장한 다음 다음 크기와 비교해야 합니다. 이제 업데이트를 모니터링할 수 있으므로 각 업데이트에서 readline 메서드를 호출합니다.
이제 한 가지 더 큰 문제가 있었는데, 각 이벤트에서 전체 파일을 읽고 전송하고 있었다는 것입니다. 여기에는 포인터를 유지하고 마지막 줄로 이동하는 간단한 솔루션이 있으며 파일을 다시 읽을 때 마지막 포인터에 도달한 후에만 줄을 인쇄합니다.
// Read file line by line
let pointer = 0;
// Keep a watch on file value change
fs.watchFile(filename, (curr, prev) => {
if (curr.size.valueOf() === prev.size.valueOf())
return;
let currentpointer = 0;
var readline = require('readline');
var rl = readline.createInterface(process.stdin, process.stdout);
rl.on('line', (log) => {
currentpointer++
if (currentpointer > pointer)
console.log(`Log is: ${log}`);
rl.close();
});
pointer = currentpointer;
});
이것은 필요에 따라 작동했지만 여전히 문제가 있었습니다. 이벤트가 발생할 때마다 로그 라인을 인쇄하지 않았지만 각 라인을 통과하고 시간과 메모리를 소모했기 때문에 비효율적이었습니다.
그래서 나는 파일의 특정 줄에서 읽을 수 있는 readline 대안을 찾기 시작했습니다. 읽을 수 있는 부분을 전달할 수 있지만 라인이 아닌 시작 바이트를 전달해야 하는 간단한 "읽기"메서드가 있습니다. 그래서 저는 이것을 사용했습니다. 이제 라인을 읽는 대신 버퍼를 읽고 포인터를 라인에서 버퍼 바이트로 변경했습니다.
이제 파일을 열고 마지막 이벤트에서 읽은 마지막 바이트부터 읽어야 합니다. 이제 라인 데이터 대신 버퍼가 생겼기 때문에 버퍼에서 일반 문자열로 변환한 다음 줄 바꿈인 "\n"으로 문자열을 분할한 다음 배열 요소를 하나씩 인쇄했습니다.
// Keep a watch on file value change
fs.watchFile(filename, (curr, prev) => {
if (filename) {
//Check if file is actually updated
if (curr.size.valueOf() === previousFileSize.valueOf())
return;
let buffer = new Buffer.alloc(curr.size - lastReadByte + 1);
previousFileSize = curr.size;
console.log(`${filename} file Changed`);
fs.open(filename, fileOpenMode, (err, filedata) => {
if (err)
return console.error(err);
console.log("Reading the file");
fs.read(filedata, buffer, 0, buffer.length, lastReadByte, (err, bytes) => {
if (err)
return console.error(err);
if (bytes > 0) {
const dataString = buffer.slice(0, bytes).toString();
const dataArray = dataString.split("\n");
dataArray.forEach(logline => {
if (logline)
console.log(logline)
});
}
lastReadByte = stats.size
// Close the opened file.
fs.close(filedata, (err) => {
if (err)
return console.error(err);
console.log("File closed successfully");
});
});
});
}
});
따라서 이것은 Node JS에서 구현된 지속적으로 업데이트되는 파일을 추적하는 효율적인 방법입니다. 해피코딩!! 더 많은 콘텐츠를 보려면 내 YTchannel를 구독하세요.
Reference
이 문제에 관하여(Node JS에서 "Tail -f"구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/shaikhkamran/implementing-tail-f-in-node-js-59g2텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)