使用Zx.js框架更方便的操作shell

 zx.js是google最近频繁更新的一个github代码库,它的作用是将JavaScript和传统的shell命令相结合,使得开发者拥有更强大的操控能力。

先来简单介绍一下shell,shell 是一个用 C 语言编写的程序,bash是大多数Linux系统以及Mac OS X默认的shell,shell是用户和Linux之间的桥梁,它是一种命令式语言,当我们执行shell脚本的时候,可以打开终端,输入命令后回车执行,例如我们平时常用的cd mydir就是一条shell基础命令;同时它又是一种程序设计语言,可以以编程的方式来进行书写,它支持变量,数组,以及运算符操作等等,传统的shell脚本通常以.sh执行脚本文件结尾。

shell命令大家在日常开发中都会经常使用,比如进入目录,创建、移动、删除文件,查看文件夹内容、操作git命令等等,但是shell文件并不一定每个开发人员都写过,正是由于shell的语法特殊性使得它有一定的学习成本,苛刻的缩进规则和啰嗦的语法规则往往让编写shell头痛不已;

我们看下面这段while循环代码:

1 int=1
2 while(( $int<=5 ))
3 do
4     echo $int
5     let "int++"
6 done

再看一段比较运算符的代码:

a=10
b=20

if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi

 

可能到这里一些前端开发工程师还不太理解为什么要用shell,前端开发明明都会写node,我们也经常使用node的基础模块来跟操作系统打交道啊,像我们平时用的fs模块,os模块都挺好用的。没错,虽然node为我们封装了一些控制操作系统的能力,但是它只是shell能力的冰山一角,还不能完全代替shell,这就是node中child_process模块存在的原因。

下图展示了使用child_process在JS文件中调用shell的方式, 相当于执行了shell的ls -lh /usr语句,但是开发者需要在输入shell命令的时候先对命令和参数进行一定格式转换,这种侦听事件回调的调用方式使用起来非常割裂且繁琐

const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);

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}`);
});

 

zx.js的作者希望以更加友好的方式让前端工程师既能用JS方便的执行shell脚本。

需要说明的是,为了能够在zx语句中让await语法在顶层使用,需要创建.mjs为扩展名的文件,它代表zx的可执行脚本文件,如果依然坚持用js文件,需要将脚本包装在void async function () {...}()中,推荐使用mjs文件创建,更加简单清晰;;

zx.js提供了一些全局函数,如$,cd,fetch等,且无需导入;

 

如$`command`的语法执行shell,$操作符像jQuery的$一样方便,随时随地调用,非常方便且自然,在js文件中。

上面的语句可以在js中直接写作:

$`ls -lh /usr`

 

一个小小的$,即把 child_process封装在内,和JS之间的相互调用浑然天成

const processOutput = $`ls -lh /usr`
console.log(processOutput.stdout) // 输出内容

 

processOutput对象定义如下,可以通过此对象获取到输出的错误和文本内容等;

class ProcessOutput {
  readonly stdout: string
  readonly stderr: string
  readonly exitCode: number
  readonly signal: 'SIGTERM' | 'SIGKILL' | ...
  toString(): string
}

 

zx.js也内置了一些函数,使开发者能够更加方便的调用shell命令

cd:

cd('/tmp')
await $`pwd` // outputs /tmp

 

fetch:

let resp = await fetch('https://wttr.in')
if (resp.ok) {
  console.log(await resp.text())
}

 

sleep:

await sleep(1000)

 

等等

 

posted @ 2022-03-28 10:15  zhishaofei3  阅读(966)  评论(0编辑  收藏  举报