fwind's blog

coder


  • Home

  • Archives

Node.js 下使用 gm 模块的一些思考

Posted on 2019-11-14

楔子

在早些年开发 Node.js 项目的过程中,我使用过其子进程(child_process)模块的部分功能,当时需要在 Node.js 的程序中使用 Linux 下的一个命令来处理一些数据。比如实现一个使用 ls 命令来查看当前目录结构的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 这是 Node.js 官方版本 12.x 文档下提供的一个实现例子 [Child Process | Node.js v12.13.0 Documentation](https://nodejs.org/dist/latest-v12.x/docs/api/child_process.html#child_process_child_process_spawn_command_args_options)
const { spawn } = require(‘child_process’);
const ls = spawn(‘ls’, [‘-lh’, ‘/Users’]);

// 控制台正常输出
ls.stdout.on(‘data’, (data) => {
console.log(`stdout: ${data}`);
});

// 控制台异常输出
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});

// 关闭
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});

事实上,我们可以通过以上方式,来实现任何与本地 Linux 服务交互的工作。任何 Linux 服务器下的系统命令,或者安装的第三方软件,均可以通过 Node.js 来使用。

达摩克利斯之剑

当时只是觉得这个功能好玩、实用,但是没有进一步深入研究。直到 周下载量过 200万的 npm 包被注入恶意代码 事件的发生,让我意识到 Node.js 的子进程功能还是一把达摩克利斯之剑。在安全防范较低或者没有的情况下,极其容易被恶意利用,而且后果不堪设想。

当然,该事件当中还藏着另外一把达摩克利斯之剑:JavaScript 下的 eval 函数 。eval 函数中可以执行几乎所有的 JavaScript 代码,简直就是一个行走的编译器。在使用该函数时,同样需要做好相关的安全工作,比如限制未知用户往里面传入任何数据。

当然,事件热的时候,关注过,凉了之后也就不了了之。

又见,思考

直到最近一段时间,在做一个项目,需要对图像文件做一下处理。在 Linux/Mac 下有一个图形图像处理工具,叫 imagemagick ,里面有瑞士军刀般多的好用功能。下意识中,我就想到了使用 Node.js 的子进程功能来直接使用。但是我又觉得这么实现似乎过于简单,而且太依赖本地环境。

于是,我就去 Node.js 官网查找了一下,看有没有新增处理图形图像的新特性,很遗憾,并没有!但是我并没死心,又继续在 bing 中搜索了一下。这时我找到一片文章(nodejs图片处理工具gm用法),介绍了如何在 Node.js 环境下,使用 npm 包 gm 来处理图形图像文件。

我很高兴,并认为这是一个理想的方案,因为那篇文中关于 gm 的介绍十分清楚,并且使用起来也很简洁。在甚至连 gm 在 npm 官网上的使用手册都没有看的前提下,我就贸然使用了 gm 。

当我激动地盯着屏幕,看着那段脚本启动,然后报异常后,我的心情先是失落,然后转为意外,最后,我静静地笑了。因为异常提示没有找到 convert 命令,而 convert 命令正是我上面提到 imagemagick 工具一下的一个命令。所以我推测这个 gm 包其实就是按照我最初的那种思路实现的。

为了一探究竟并验证我的想法。首先,我看了 gm 在 npm 上的官方使用手册。果然,文档的一开始就清楚的提示,使用该工具之前需要先安装 imagemagick 。那它到底是如何使用的 imagemagick 呢?让我们接着往下看。

我看了 gm 的源码。果然, gm 引用了一个叫 cross-spawn 的包,来执行 convert 命令,而 cross-spawn 的源码中,确实是使用 child_process 子进程来实现的。

到此为止,整个过程已经理顺。而我则陷入了沉思……

可想而知,利用这种模式,即 Node.js + child_process 的方式,可以实现很多基于操作系统命令行的功能。在没有遇到 gm 之前,我只是简单地这么认为。在遇到 gm 之后,我才发现,原来真的有工程师利用这种模式来输出被广泛( gm 在 npm 上的周下载量,截止我写这篇文章为止,已经超 10 万了)使用的工具。有时候,编程技术迭代很快,日新月异,每隔一段时间就会有一个新的很炫酷的技术冒出来,然后受到大家的追捧。而有时候,编程技术迭代又很慢,很多技术明明是新瓶装旧酒,却同样可以焕发出耀眼的光芒。

所以说,在计算机这一行,如果你真心的热爱她,就应该沉下心来,认真地去理解和感悟技术的本质,而不是去一个劲儿地追逐新时髦。唯有看透本质,才是获取真理钥匙的最佳途径。

npm 中 dependencies 和 devDependencies 的使用

Posted on 2019-11-07

导读

使用 npm 作为包管理工具已经很多年了,但是常用的其实就那么几个功能,一些基础的但很重要的概念和用法反而不太清楚。最近抽空整理并探索一下,重新学习 npm 。

今天先对 package.json 配置文件中的 dependencies 和 devDependencies 做一番研究。

dependencies

  1. 使用环境:生产环境下所依赖的 npm 包集合;
  2. 命令行安装单个包的方式:

    1
    2
    3
    4
    # 在与 package.json 同级目录下执行
    # —sava-prod 为默认安装模式
    # 安装以后会自动在 package.json 的 dependencies 下添加 <package-name>
    npm install <package-name> [—sava-prod]
  3. 命令行集成安装方式:

    1
    2
    3
    4
    5
    # 在与 package.json 同级目录下执行
    # 安装 dependencies 和 devDependencies 中的所有 npm 包
    npm install
    # 仅安装 dependencies 下的所有 npm 包
    npm install —production
  4. 被调用:如果将当前工程作为一个单独包,提供给其他人使用,在对方使用 npm install 命令安装时,会自动下载 dependencies 下的包集合。

devDependencies

  1. 使用环境:开发和测试环境下所依赖的 npm 包集合;
  2. 命令行安装单个包的方式:

    1
    2
    3
    # 在与 package.json 同级目录下执行
    # 安装以后会自动在 package.json 的 devDependencies 下添加 <package-name>
    npm install <package-name> —sava-dev
  3. 命令行集成安装方式:

    1
    2
    3
    # 在与 package.json 同级目录下执行
    # 安装 dependencies 和 devDependencies 中的所有 npm 包
    npm install
  4. 被调用:如果将当前工程作为一个单独包,提供给其他人使用,在对方使用 npm install 命令安装时,不会自动下载 devDependencies 下的包集合。

建议

部署

在我以往写代码的过程中,对于需要引用包的位置,并没有做任何区分,因为在使用 npm install 时会一起安装,所以没有太在意,直到使用 nest.js 时发现,默认安装的包居然有 200M 之多。

当我需要自动化部署它们到一台线上服务器时,会花费很多时间,但其实像 @nestjs/cli 、 @types/supertest 等开发和测试工具在线上根本是用不着的。

于是我对于要往线上环境上传的工程使用了 npm install —production 命令,这时文件大小缩小为 11M ,然后再压缩以后,最终仅仅剩下了 5M 。

发布

当整个工程开发完毕,作为一个独立包待发布时,同样需要注意!如果不对 dependencies 和 devDependencies 加以区分,将开发/测试依赖写在生产依赖下,会导致调用该 npm 包的用户下载很多与其无关的包,从而造成不必要的资源浪费。

参考来源

Specifying dependencies and devDependencies in a package.json file | npm Documentation
npm install 你很明白吗 - NeverYu - CSDN博客

记一次在 github 上提交 issue 的经历

Posted on 2019-11-01

起因

在一次使用 vs code 时,发现一个 bug :使用中文路径 split terminal (终端分屏)时会报异常并且失败,英文路径是ok的。

经过

确认 bug

然后我在不同场景下试图复现这个 bug :

  1. 使用 vs code 新建一个工程,然后新建中文目录, bug 会 100% 复现;
  2. 在 vs code 中选择不同 shell , bash 和 zsh , bug 仍旧 100% 复现;
  3. 因为vs code的终端是基于本地系统的,所以我在本地终端中,新建中文文件,然后基于该路径,使用终端软件自带分屏功能进行分屏,并没有出现 bug ,排除终端问题。

提交 bug

目前来看,这个应该是 vs code 的一个 bug,实锤了。因此我决定将这个 bug反馈给 vs code 的工作人员。

之前在使用 vs code 时,无意中发现右下角有个笑脸,是用来接收反馈信息的,于是乎我现在选择触发它。

触发以后,点击“提交 bug ”,会弹出一个界面,用于填写bug内容,这里需要使用英文编辑(如果是中文提问,工程师会告诉你他不会中文,并无情地关闭 issue )。然后点击“在 github 预览”会跳转到 github 下(需要登录),此时如果不需要编辑,直接 submit issue 就好。

来自工程师的响应

在提交完 issue 以后的第二天早上,我收到了来自 vs code 工作人员的回复,一位来自澳大利亚的软件工程师,他告诉我提交该类型的 issue ,还需要提供一下我的 vs code 版本信息,最好还有 bug 复现的视频、动图或者截屏。

得到对方的及时回复(毕竟有时差),我还是有点小激动的。然后按照对方提示,我认真的准备了 vs code 版本信息和 bug 复现动图,并再一次提交。

这一次,在当天晚上我就得到了回复,对方提供了解决方案,修改 setting 配置,在分屏时自动返回到 vs code 工程的父路径。这样配置以后,中文路径分屏确实不报异常了,但是却修改了我原本的使用习惯。于是乎,我把这个情况再一次反馈回去。

这位来自澳大利亚的帅气工程师,这次是这么回复的:你提的问题我们后续会修复,之前告诉你的也只是当前的解决方案。简洁并且直爽,人家之所以给你提之前的方案,并不是说 bug 不存在,只是另一个解决方式,bug我们还是会改,但是你得等待。

结果

到此为止,我认为我的目的达到了,于是乎就把这个issue关了。但是没过多久,这个工程却重新打开了 issue 。我没有再追问,我推测在 bug 修复之前, issue 应该是不会关闭,具体是不是这个澳洲小伙修复就不得而知了。

关于这次issue的整个过程,在 github 上完成过程,感兴趣的同学可以自行查阅。(terminal.integrataed.splitCwd inherited doesn’t work correctly for unicode characters · Issue #83496 · microsoft/vscode · GitHub)

Linux服务器守护进程方案及实现

Posted on 2019-10-10

总体思路

  1. 在linux服务器新建无登录账号(/sbin/nologin/)
  2. 构建自动化启动进程脚本
  3. 新建计划任务定时监控服务(crontab)

初衷

在服务器的管理中,我们需要启动一些服务,出于安全方面的考虑,我们不希望以root的方式启动它,而是为这些服务单独建立相应的账号,并且禁用它们的shell登录权限。

实现过程

场景说明

在linux服务器上实现对于nodejs进程进行守护的场景。

构建nodejs程序

  1. 我们新建一个nodejs程序server.js:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const http = require(‘http’)
    const server = http.createServer(function (req, res) {
    res.writeHead(200, {
    ‘Content-Type’: ‘application/json’
    });
    res.end(‘{“server”:”nodejs”}’);
    });
    server.listen(8080)
    console.log(“port = 8080”)
  2. 常规启动:

    1
    node server.js

启动以后,server.js进程属于root用户,或者其他可以shell登录的用户:

  1. 在浏览器敲入ip加端口即可查看运行结果:

新建无登录账号

  1. 新建账号:

    1
    useradd -M -s /sbin/nologin nodejsUser
  2. 在/etc/passwd下查看账号状态:

    nodejsUser是无法shell登录的,我们可以使用如下命令启动server.js:

    1
    2
    3
    4
    # 赋予nodejsUser账号可访问server.js文件的权限
    sudo chown nodejsUser /opt/nodejsUser/server.js
    # 启动
    sudo -u nodejsUser node /opt/nodejsUser/server.js
  3. 此时查看8080端口,可以发现,现在用户是nodejsUser了:

编写自动化启动脚本

  1. 此处我们需要借助tmux工具来实现实时监控nodejs进程的功能,下面是具体实现过程server.sh:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #!/bin/bash
    # tumx启动脚本

    # 兼容zsh
    export DISABLE_AUTO_TITLE="true"
    # 会话名称
    session=“sever”
    # 判断server.js进程是否存在
    ps -ef|grep "node /opt/nodejsUser/server.js" |grep -v grep
    if [ $? -ne 0 ]
    then
    echo "start process....."
    # 判断tmux会话是否存在
    tmux has-session -t $session
    if [ $? = 0 ]
    then
    # 如果存在,则进入该会话
    tmux attach-session -t $session
    else
    # 如果不存在,则新建会话
    tmux new-session -d -s $session
    fi
    # 发送启动程序命令
    tmux send-keys -t $session "sudo -u nodejsUser node /opt/nodejsUser/server.js" C-m
    else
    echo "runing....."
    fi
    exit
  2. 当tmux会话启动以后,可以随时查看server.js运行的情况:

    1
    2
    # 	启动会话
    tmux a -t server

自定义计划任务

  1. 新建计划任务:

    1
    crontab -e
  2. 任务内容:

    1
    */1 * * * * /bin/bash /opt/nodejsUser/server.sh >> /opt/nodejsUser/run.log 2>&1

每分钟执行一次server.sh脚本,执行情况记录到日志文件run.log当中。crontab的定时机制可以自行查阅,比较好理解,这里不再赘述。

写在最后的话

到此为止,所有功能均已实现,我们的计划任务会定时对server.js进程扫描,当发现该进程crash时,会自动重启。当服务器重启时,计划任务也会超常运行。

其实在这之前,我在管理nodejs项目时,使用的是pm2监控工具,现成的免费工具,用起来确实也比较方便,但是在无登录账号下遇到无法启动pm2的问题,虽然花了一些时间攻克,但最终并没有解决,因此就有了本文中的解决方案,先用一段时间看看效果吧。

ES6函数简写及思考

Posted on 2019-09-26

初闻

一次,一个同事在群里问,有谁知道这个函数该如何用ES6的方式简写:

1
2
3
4
5
function fn(n){
return function(m){
return m+n
}
}

我当时也没动脑子,直接按潜意识改了一下,发出去了:

1
2
3
4
5
fn=(n)=>{
return (m)=>{
return m+n
}
}

果然,发code的那家伙神秘一笑,说你再继续简化一下试试。我后背一凉,赶紧又看了看,改成这个样子又抛出去了:

1
2
3
fn=(n)=>(m)=>{
return m+n
}

我自认为这种总该差不多了吧,结果又被生生打脸。题主笑而不语,然后我恍然大悟,看来之前真是自以为会用,根本没有认真思考过,其实还可以进一步简化:

1
fn=(n)=>(m)=> m+n

最后题主说,把括弧也去了吧:

1
fn = n => m => m + n

看着这段code,我沉默了……原来code可以如此简洁、优美、易懂。

偶遇

上面的故事发生没多久以后,我在看一个帖子时,发现如下code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [
{ name:"小明", age:12 },
{ name:"小红", age:11 },
{ name:"小刚", age:15 },
{ name:"小华", age:13 }
];
function compare(p) { //这是比较函数
return function (m, n) {
var a = m[p];
var b = n[p];
return a - b; //升序
}
}
arr.sort(compares("age"));
console.log(arr);

然后我笑了,在评论区默默地留下了compares函数的简版:

1
compare = p => (m, n) => m[p] - n[p]

思考

Coding这么多年,其实大部分时间是比较麻木的,不走脑子的reading、copy以及coding,糊弄完了一个又一个项目。随着时光的飞逝,真正有意义的东西很少能留下来,所谓很少,其实还是有的,要不真该转行了,就比如这个ES6简写的过程,就是非常有趣并且优美的。但是这个过程很偶然,首先,你得初步了解过这个技术,然后,在一个被动的机会下,你静下心来,认真的体会技术带来的愉悦感,并真正的掌握这项技能。这似乎需要一个积累的过程,大量阅读以后再反复推敲,然后在这个过程中,自我成长,体会技术的真谛,并且使自己快乐!

光学字符识别引擎tesseract-ocr入门教程—Mac标注+Ubuntu打包

Posted on 2019-08-23

概念

Tesseract是一个光学字符识别引擎,支持多种操作系统。Tesseract是基于Apache许可证的自由软件,自2006 年起由Google赞助开发。 2006年,Tesseract被认为是最精准的开源光学字符识别引擎之一。【维基百科】

声明

在使用tesseract-ocr的过程中,我遇到了一些问题,并找到了一种适合我的使用方式,在这里给大家分享一下。

困境

  1. 在Mac下使用Homebrew安装tesseract-ocr时,—with-training-tools参数取消,所以无法训练数据;如果使用github下载源码,然后编译安装的话,需要安装很多依赖,比较麻烦;
  2. 如果在ubuntu下使用apt-get安装,默认是携带各种训练工具的,但是我的ubuntu系统是server版,不支持桌面,所以在标注图片时很不方便。

    我的解决方案

    我的解决方案是:在MacOS下标注,然后把标注好的box文件送到Ubuntu Server下,打包训练语言模型。
    注意:如果您满足我在上文中提到的困境,就可以继续往下读了。

其他方案

  1. 在Mac下编译tesseract,使用jTessBoxEditor标注+训练
  2. 在Linux桌面版安装tesseract,使用jTessBoxEditor标注+训练
  3. 在Windows安装tesseract,使用jTessBoxEditor标注+训练

安装

tesseract-ocr支持Linux、Windows、MacOS、Android、IOS等操作系统。由于本人使用的操作系统是MacOS和Linux ubuntu server,所以本文只介绍这两个环境的安装。

Mac

借助Homebrew,执行命令:

1
brew install tesseract-ocr

安装完以后,截至今天为止,默认是4.0.0版本,不支持—with-training-tools,所以也不支持训练功能。如果直接使用github下载源码编译安装,是可以支持的,但是我比较懒,在需要训练操作时,我就去Linux上搞了(Linux的4.0.0是携带辅助训练工具包的)。

Linux

借助apt-get,执行命令:

1
apt-get install tesseract-ocr

基本用法

  1. 设置识别语言,默认英文(eng),中文是chi_sim(需另行下载语言包),如果需要同时识别两种或者两种以上语言,比如同时识别中文和英文,格式为“-l chi_sim+eng”,执行以下命令,识别结果会以txt文本形式保存在目标路径下。

    1
    tesseract [待识别图片路径] [目标识别结果路径] -l eng
  2. 设置文字坐标输出,执行以下命令:

    1
    tesseract [待识别图片路径] [目标识别结果路径] -l test makebox

识别结果会以box后缀文件形式保存在目标路径下,坐标内容包含识别结果左上角的横纵坐标以及长宽值,比如识别如下字符:

其结果为(啧啧啧,通用中文库识别效果很差):

数据训练

借助第三方工具

jTessBoxEditor是一款辅助标记的工具,在本地安装完tesseract-ocr以后,可以在jTessBoxEditor中配置tesseract-ocr的启动路径,然后基于tesseract-ocr进行可视化标注。如下图所示:

环境配置

在jTessBoxEditor的Trainer标签下,主要功能说明:

  1. Tesseract Executables配置tesseract程序启动路径
  2. Training Data存放训练数据路径
  3. Language为自定义训练集名称
  4. Bootstrap Language是训练之前需要借助的语言模型名称
  5. 然后选择Make Box File Only
    注意:使用jTessBoxEditor需要配置Java环境变量。

初步识别

  1. 选择Make Box File Only
  2. 点击run按钮,就可以出来借助默认语言模型执行的识别结果。

开始标注

在获取到执行结果以后,切换到Box Editor标签,如下图所示:

标注过程:

  1. 首先点击“open”按钮打,打开之前识别结果box
  2. 在左侧列表中,选择一个字符,比如上图中手写版的“测”字,然后在右侧提示框中对其进行调整,直到红色框完美包含字符
  3. 然后依次调整其余所有字符
  4. 如果需要新增标注框,点击“insert”,或者需要删除,请点击“delete”
  5. 如何需要合并两个字符,点击“merge”,或者均分字符,请点击“split”
  6. 点击“save”保存box
  7. 返回上个标签Trainer,然后选择“Train with Existing Box”,点击“run”执行
  8. 这时会在训练路径下生存.traindate语言模型
  9. 最后,再换一张与训练数据类似的图片,点击Validate进行验证。
    注意:如果你没有在Mac上编译安装tesseract,只是通过brew安装了4.x.x版本,那么到第6步就可以停止了,因为该版本不携带训练工具,你可以拿着标注好的box文件,找一个linux机器手动生存语言模型包,过程参考上述“命令行打包语言模型”。

命令行打包语言模型

  1. 使用tesseract命令生成识别结果box文件
  2. 调整box(或者直接使用jTessBoxEditor标注结果)
  3. 依次执行以下命令:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # picture.jpeg是待识别图片
    tesseract picture.jpeg picture nobatch box.train
    unicharset_extractor picture.box
    # 新建font_properties本文,内容为test 0 0 0 0 0
    shapeclustering -F font_properties -U unicharset picture.tr
    mftraining -F font_properties -U unicharset -O unicharset picture.tr
    cntraining picture.tr
    # 到此为止,会生成unicharset、inttemp、pffmtable、shapetable、normproto等五个文件,分别给他们加上test.前缀(test为自定义语言模型名称)
    combine_tessdata test.
  4. 此时会在当前目录下生成test.traineddata文件,移动该文件到tesseract-ocr的tesedata目录下(我的路径是_usr_share_tesseract-ocr/4.00_tessdata/)

  5. 然后设置语言执行识别命令:

    1
    2
    # test是刚才生成的语言模型名称
    tesseract test1.jpeg test1 -l test
  6. 执行结果:(效果还是不错的)

总结

总体而言,虽然是桌面版标注+服务器端处理,但是使用起来还是可以接受的。如果将来有时间,可以研究一下在mac下之间编译tesseract源码

pm2学习笔记

Posted on 2019-07-03

概念

PM2(process manage)是JavaScript运行时Node.js的进程管理器。

基本操作

安装

1
2
# 借助npm包管理器安装
npm install -g pm2

启动进程

命令行启动

  1. 默认启动

    1
    2
    # 启动一个nodejs进程,进程名默认为nodejs文件名,默认为fork单进程模式
    pm2 start app.js
  2. 自定义启动

    1
    2
    # 启动并自定义进程名
    pm2 start app.js --name processNames
  3. 负载均衡

    1
    2
    # 负载均衡(服务器只是满足双核及以上),max为默认最大cpu数,可以自定义
    pm2 start app.js -i max
  4. 目录监听

    1
    2
    # 监听目录变化,默认不启动
    pm2 start app.js --watch
  5. 携带参数启动

    1
    2
    # 携带test和100启动进程
    pm2 start app.js -- -test -100

配置启动脚本

  1. 首先,编辑启动脚本内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    {
    "apps": [{
    "name": "app1",
    "script": "./app1.js",
    "watch": true
    }, {
    "name": "app2",
    "script": "./app1.js",
    "watch": false
    }]
    }
  2. 然后执行启动命令

    1
    pm2 start app.json

重启进程

  1. 重启/更新单个进程
    1
    2
    3
    4
    # 重启0进程
    pm2 restart 0
    # 更新0进程
    pm2 reload 0

区别:重启的过程是先停止(stop)进程,然后再开启(start)进程,可能会造成已建立连接的实效;更新的过程是先开启(start)一个或者若干进程,同时停止旧的进程接收请求,然后旧的进程结束以后,再关闭旧的进程。

  1. 重启/更新所有进程

    1
    2
    3
    4
    # 重启所有进程
    pm2 restart all
    # 更新所欲进程
    pm2 reload all
  2. 优雅的更新一个/所有进程

    1
    2
    3
    4
    # 优雅的重启0进程
    pm2 gracefulReload 0
    # 优雅的重启所有进程
    pm2 gracefulReload all

备注:gracefulReload区别于reload的地方在于,会发送一个shutdown的消息给旧的进程,这个过程可以在程序中监听到,然后根据自己的业务逻辑进程处理。

1
2
3
4
// 这里我们可以监听到‘shutdown’,然后在里面可以自定义一些跟自己项目相关的业务逻辑
process.on('shutdown', function () {
server.close();
});

进程日志

1
2
3
4
# 实时查阅进程0的日志
pm2 log 0
# 查阅所有进程的日志
pm2 logs

停止进程

1
2
3
4
# 停止0进程
pm2 stop 0
# 停止所有进程
pm2 stop all

删除进程

1
2
3
4
# 删除0进程
pm2 delete 0
# 删除所有进程
pm2 delete all

进程列表

1
2
# 查看进程状态
pm2 list

进程监控

1
2
# 监控所有进程的实施状态
pm2 monit

保存配置

1
2
# 保存当前所有进程任务
pm2 save

还原配置

1
2
# 还原最后一个保存的所有进程任务
pm2 resurrect

应用场景

守护进程

当进程出现崩溃、异常停止等现象时,pm2会帮你重启该进程。

进程监控

实时查看进程的cpu、内存占有情况以及运行状态等。

日志管理

所有pm2日志会默认保存在~/.pm2/logs目录下,以进程名命名生成相应的日志文件,可以借助pm2-logrotate模块实现日志的按时间或者大小切割,便于归档记录,排查故障。

tmux学习笔记

Posted on 2019-06-28

概述

Tmux 是一个优秀的终端复用器类自由软件,但使用 BSD 许可发布。用户可以通过 tmux 在一个终端内管理多个分离的会话,窗口及面板,对于同时使用多个命令行,或多个任务时非常方便。

基本操作

会话

  1. 新建会话

    1
    2
    3
    4
    # 新建会话,会话名默认生成
    tmux
    # 新建会话,并声明会话名
    tmux new -s session_name
  2. 正在运行会话列表查阅

    1
    tmux ls
  3. 打开一个正在运行会话

    1
    tmux a -t session_name
  4. 退出当前会话
    快捷键:control+b,d

  5. 删除会话
    1
    2
    3
    4
    # 删除一个正在运行的会话
    tmux kill-session -t session_name
    # 删除当前会话名以外的其余会话(不指定会话名,默认保留第一条会话)
    tmux kill-session -a -t session_name

分屏

  1. 横向分屏
    快捷键:control+b,%
  2. 纵向分屏
    快捷键:control+b,”

杂项

  1. 移动光标
    快捷键:control+b,方向键
  2. 显示系统时间
    快捷键:control+b,t
  3. 关闭窗口
    在当前会话下,将光标移动到待关闭窗口,然后敲命令exit即可关闭窗口。

应用场景

代码调试

在Linux或者Mac终端水平或者垂直切割屏幕,将切割区域分为代码部分、编译部分、调试效果展示部分、日志记录部分等,当我们需要debug时:在代码部分敲入代码,然后在代码编译部分编译代码,最后在展示部分(可终端展示程序)查看效果,如果有问题呢,在日志部分也可以实时检查。可谓码农的编程利器啊!

系统监控

我们可以建立多个会话,分别监控我们需要关注的系统性能、报警等信息,比如cpu使用情况、网络使用情况、内存是否正常、磁盘是否够用等等,然后在每个会话里,我们还可以通过屏幕切割达到对于每项监控更加细致的分类,一目了然,掌控全局!

记忆标签

本地

很多使用Mac的同学都一个不成文的习惯,电脑长时间不关机,并且同时开启很多终端,原因有很多,比如担心重启电脑以后丢失之前进行到一半的任务,或则只是因为懒……当然,mac本身设计的很好,就算长期不重启也毫无压力。这个时候,其实我们需要一个记忆标签工具,来管理我们打开的数量庞大的终端们。不管开启多少个终端,只要我们简单的取个名字作为标记,下次再找的时候会快捷很多!

服务器

对于服务器来说,重启的机会更加微乎其微,这个时候,我们就更需要一个终端记忆标签工具来管理我们的远程会话了,当我们ssh连接服务器时,遇到突发事件,比如被叫去开会,或者下班了,没关系!在开完会或者第二天上班以后,我们还可以进入当时那个会话,继续之前没有完成的工作。

ssh学习笔记

Posted on 2019-06-24

介绍

Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。

连接方式

秘密验证

连接命令:

1
ssh username@ip

注释:其中username是服务器的用户名,ip是服务器的地址,然后输入服务器端该用户的登录密码即可完成连接验证。

密钥验证

  1. 生成密钥
    在客户端生成公钥和私钥,此处我们使用rsa作为加密方式(加密方式另外还有rsa1、ecdsa、ed25519、dsa等),使用以下命令生成密钥:
    1
    ssh-keygen -t rsa

并设置文件名和秘密(这里我们定义文件名为id_rsa),然后会在目录~.ssh下生成私钥文件id_rsa和公钥文件id_rsa.pub。

  1. 连接验证
    生成密钥文件以后,将公钥放置在服务器端的目录~_.ssh_authorized_keys下,然后在客户端使用私钥进行免秘密验证,连接命令:
    1
    ssh -i ~/.ssh/id_rsa username@ip

快速连接配置

在文件目录~.ssh下有个config文件,我们可以将上文两种连接方式中写在里面,然后直接以ssh+服务器简称的方式进行快速连接。

  1. 秘密配置
    1
    2
    3
    4
    Host    server01
    HostName 192.168.1.10
    Port 22
    User username

注释:22是ssh的默认连接端口(可变更)。配置完成以后,可以通过以下命令连接,连接时需要再次输入密码。

1
ssh server01

  1. 密钥配置
    1
    2
    3
    4
    5
    Host    server02
    HostName 192.168.1.11
    Port 22
    User username
    IdentityFile ~/.ssh/id_rsa

注释:其中IdentityFile为私钥文件的路径。配置完成以后,可以通过以下命令连接,连接时无需再次输入密码。

1
ssh server02

搭建通道

最简单的文件复制通道,执行命令:

1
scp -i ~/.ssh/id_rsa '待传送文件' username@ip:'目标传送目录'

通过以上命令,可以建立客户机和服务器之间或者两台服务器之间,文件单向传送的通道。

安全性

SSH旨在保证非安全网络环境(例如互联网)中信息加密完整可靠。不过,SSH它也被指出有被嗅探甚至解密的漏洞。这里我们就不做具体介绍了。

linux下root用户连接ssh

Posted on 2019-05-28

linux,ubuntu,root,xshell,ssh

  • 启用root用户
  1. 配置过程
    [workspace]@username:~$ sudo passwd root
    [sudo] password for fwind: 
    Enter new UNIX password: 
    Retype new UNIX password: 
    passwd: password updated successfully
    workspace@username:~$ reboot
    
  2. 完成
    root@username:~$
    
  • 连接ssh
  1. 修改配置文件
    使用root权限用户打开ssh配置文件:
    vim /etc/ssh/sshd_config
    
    找到“PermitRootLogin prohibit-password”一行,将“prohibit-password”改为“yes”,然后重启ssh服务;
  2. 重启
    在root下重启ssh服务,然后。。。就可以在xshell下使用ssh肆无忌惮的连接linux了。
    sudo service sshd restart
    

ps: vim 是linux下一款非常强大的编辑器,后续会有相关使用心得,敬请期待!

12

fwind

code

13 posts
7 tags
© 2025 fwind
Powered by Hexo
|
Theme — NexT.Muse v5.1.4