Nodejs进阶:readline实现日志分析+简易命令行工具

简介: readline是个非常实用的模块。如名字所示,主要用来实现逐行读取,比如读取用户输入,或者读取文件内容。常见使用场景有下面几种,本文会逐一举例说明。本文相关代码可在笔者github上找到。

本文摘录自《Nodejs学习笔记》,更多章节及更新,请访问 github主页地址。欢迎加群交流,群号 197339705

模块概览

readline是个非常实用的模块。如名字所示,主要用来实现逐行读取,比如读取用户输入,或者读取文件内容。常见使用场景有下面几种,本文会逐一举例说明。本文相关代码可在笔者github上找到。

  • 文件逐行读取:比如说进行日志分析。
  • 自动完成:比如输入npm,自动提示"help init install"。
  • 命令行工具:比如npm init这种问答式的脚手架工具。

基础例子

先看个简单的例子,要求用户输入一个单词,然后自动转成大写

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question('Please input a word: ', function(answer){
    console.log('You have entered {%s}', answer.toUpperCase());
    rl.close();
});

运行如下:

  toUpperCase git:(master)  node app.js 
Please input a word: hello
You have entered {HELLO}

例子:文件逐行读取:日志分析

比如我们有如下日志文件access.log,我们想要提取“访问时间+访问地址”,借助readline可以很方便的完成日志分析的工作。

[2016-12-09 13:56:48.407] [INFO] access - ::ffff:127.0.0.1 - - "GET /oc/v/account/user.html HTTP/1.1" 200 213125 "http://www.example.com/oc/v/account/login.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
[2016-12-09 14:00:10.618] [INFO] access - ::ffff:127.0.0.1 - - "GET /oc/v/contract/underlying.html HTTP/1.1" 200 216376 "http://www.example.com/oc/v/account/user.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
[2016-12-09 14:00:34.200] [INFO] access - ::ffff:127.0.0.1 - - "GET /oc/v/contract/underlying.html HTTP/1.1" 200 216376 "http://www.example.com/oc/v/account/user.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"

代码如下:

const readline = require('readline');
const fs = require('fs');

const rl = readline.createInterface({
    input: fs.createReadStream('./access.log')
});

rl.on('line', (line) => {
    const arr = line.split(' '); 
    console.log('访问时间:%s %s,访问地址:%s', arr[0], arr[1], arr[13]);
});

运行结果如下:

  lineByLineFromFile git:(master)  node app.js
访问时间:[2016-12-09 13:56:48.407],访问地址:"http://www.example.com/oc/v/account/login.html"
访问时间:[2016-12-09 14:00:10.618],访问地址:"http://www.example.com/oc/v/account/user.html"
访问时间:[2016-12-09 14:00:34.200],访问地址:"http://www.example.com/oc/v/account/user.html"

例子:自动完成:代码提示

这里我们实现一个简单的自动完成功能,当用户输入npm时,按tab键,自动提示用户可选的子命令,如help、init、install。

  • 输入np,按下tab:自动补全为npm
  • 输入npm in,按下tab:自动提示可选子命令 init、install
  • 输入npm inst,按下tab:自动补全为 npm install
const readline = require('readline');
const fs = require('fs');

function completer(line) {
    const command = 'npm';
    const subCommands = ['help', 'init', 'install'];

    // 输入为空,或者为npm的一部分,则tab补全为npm
    if(line.length < command.length){
        return [command.indexOf(line) === 0 ? [command] : [], line];
    }

    // 输入 npm,tab提示 help init install
    // 输入 npm in,tab提示 init install
    let hits = subCommands.filter(function(subCommand){ 
        const lineTrippedCommand = line.replace(command, '').trim();
        return lineTrippedCommand && subCommand.indexOf( lineTrippedCommand ) === 0;
    })

    if(hits.length === 1){
        hits = hits.map(function(hit){
            return [command, hit].join(' ');
        });
    }
  
    return [hits.length ? hits : subCommands, line];
}

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  completer: completer
});

rl.prompt();

代码运行效果如下,当输入npm in,按下tab键,则会自动提示可选子命令init、install。

  autoComplete git:(master)  node app.js
> npm in
init     install  

例子:命令行工具:npmt init

下面借助readline实现一个迷你版的npm init功能,运行脚本时,会依次要求用户输入name、version、author属性(其他略过)。

这里用到的是rl.question(msg, cbk)这个方法,它会在控制台输入一行提示,当用户完成输入,敲击回车,cbk就会被调用,并把用户输入作为参数传入。

const readline = require('readline');
const fs = require('fs');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: 'OHAI> '
});

const preHint = `
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See \`npm help json\` for definitive documentation on these fields
and exactly what they do.

Use \`npm install <pkg> --save\` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
`;

console.log(preHint);

// 问题
let questions = [ 'name', 'version', 'author'];

// 默认答案
let defaultAnswers = [ 'name', '1.0.0', 'none' ];

// 用户答案
let answers = [];
let index = 0;

function createPackageJson(){
    var map = {};
    questions.forEach(function(question, index){
        map[question] = answers[index];
    });

    fs.writeFileSync('./package.json', JSON.stringify(map, null, 4));
}

function runQuestionLoop() {

    if(index === questions.length) {
        createPackageJson();
        rl.close();
        return;
    }
    
    let defaultAnswer = defaultAnswers[index];
    let question = questions[index] + ': (' + defaultAnswer +') ';
    
    rl.question(question, function(answer){
        answers.push(answer || defaultAnswer);
        index++;
        runQuestionLoop();
    });
}

runQuestionLoop();

运行效果如下,最后还像模像样的生成了package.json(害羞脸)。

  commandLine git:(master)  node app.js

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.

name: (name) hello
version: (1.0.0) 0.0.1
author: (none) chyingp

写在后面

有不少基于readline的有趣的工具,比如各种脚手架工具。限于篇幅不展开,感兴趣的同学可以研究下。

相关链接

https://nodejs.org/api/readline.html

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
SQL JSON 监控
新功能:日志服务命令行工具ETL发布!
日志服务命令行工具ETL发布,解决数据采集、分析查询、投递归档、外部整合过程中的数据规整痛点,提供实时、可靠、可扩展、可管理的运行模式支持,以及全面简单的ETL规则,并支持丰富的扩展支持。
3672 0
|
1月前
|
安全 Linux 网络安全
/var/log/secure日志详解
Linux系统的 `/var/log/secure` 文件记录安全相关消息,包括身份验证和授权尝试。它涵盖用户登录(成功或失败)、`sudo` 使用、账户锁定解锁及其他安全事件和PAM错误。例如,SSH登录成功会显示&quot;Accepted password&quot;,失败则显示&quot;Failed password&quot;。查看此文件可使用 `tail -f /var/log/secure`,但通常只有root用户有权访问。
103 4
|
1月前
|
运维 监控 数据可视化
日志服务 HarmonyOS NEXT 日志采集最佳实践
鸿蒙操作系统(HarmonyOS)上的日志服务(SLS)SDK 提供了针对 IoT、移动端到服务端的全场景日志采集、处理和分析能力,旨在满足万物互联时代下应用的多元化设备接入、高效协同和安全可靠运行的需求。
116776 10
|
1月前
|
监控 Linux 网络安全
/var/log/auth.log日志说明
`/var/log/auth.log`是Linux系统记录身份验证和授权事件的日志文件,包括登录尝试、SSH连接、sudo操作等。系统管理员可通过它监控用户登录、检查失败尝试、跟踪SSH活动、查看sudo/su操作及PAM活动。日志内容可能因系统配置而异,可能存在于其他日志文件中。分析这些日志可使用`tail`、`grep`等命令或专用日志分析工具。了解系统和其服务详情有助于提取有用信息。
53 2
|
1月前
|
安全 Ubuntu Unix
/var/log/syslog日志说明
`/var/log/syslog`是Unix和Linux的日志文件,记录系统事件和消息,由`syslogd`或`rsyslogd`生成。日志条目含时间戳、主机名、PID、日志级别(如DEBUG、ERROR)和事件描述。内容涵盖系统启动/关闭、硬件错误、网络、用户登录、安全事件等。查看日志可使用`cat`、`tail`、`less`或`grep`命令。不过,不同Linux发行版可能有变,如Ubuntu使用`journald`和`journalctl`。
55 3
|
3天前
|
C++
JNI Log 日志输出
JNI Log 日志输出
12 1
|
3天前
|
存储 运维 大数据
聊聊日志硬扫描,阿里 Log Scan 的设计与实践
泛日志(Log/Trace/Metric)是大数据的重要组成,伴随着每一年业务峰值的新脉冲,日志数据量在快速增长。同时,业务数字化运营、软件可观测性等浪潮又在对日志的存储、计算提出更高的要求。
|
10天前
|
XML Java Maven
Springboot整合与使用log4j2日志框架【详解版】
该文介绍了如何在Spring Boot中切换默认的LogBack日志系统至Log4j2。首先,需要在Maven依赖中排除`spring-boot-starter-logging`并引入`spring-boot-starter-log4j2`。其次,创建`log4j2-spring.xml`配置文件放在`src/main/resources`下,配置包括控制台和文件的日志输出、日志格式和文件切分策略。此外,可通过在不同环境的`application.yml`中指定不同的log4j2配置文件。最后,文章提到通过示例代码解释了日志格式中的各种占位符含义。
|
10天前
|
运维 监控 Go
Golang深入浅出之-Go语言中的日志记录:log与logrus库
【4月更文挑战第27天】本文比较了Go语言中标准库`log`与第三方库`logrus`的日志功能。`log`简单但不支持日志级别配置和多样化格式,而`logrus`提供更丰富的功能,如日志级别控制、自定义格式和钩子。文章指出了使用`logrus`时可能遇到的问题,如全局logger滥用、日志级别设置不当和过度依赖字段,并给出了避免错误的建议,强调理解日志级别、合理利用结构化日志、模块化日志管理和定期审查日志配置的重要性。通过这些实践,开发者能提高应用监控和故障排查能力。
87 1
|
11天前
|
弹性计算 运维 Shell