首页 > 系统相关 >译:使用 Bun 执行 Shell 脚本

译:使用 Bun 执行 Shell 脚本

时间:2024-01-30 21:35:42浏览次数:26  
标签:脚本 Shell await js shell bun ls Bun

原文地址(Bun Blog): https://bun.sh/blog/the-bun-shell

作者: jarredsumner

发布时间:2024-01-20

前言

JavaScript 是世界上最流行的脚本语言。

那么为什么在 JavaScript 中执行 Shell 脚本很困难呢?

import { spawnSync } from 'child_process'

// 代码比想象中要稍微复杂一些
const { status, stdout, stderr } = spawnSync('ls', ['-l', '*.js'], {
  encoding: 'utf8',
})

你也可以使用内置的 API 来执行类似的操作:

import { readdir } from 'fs/promises';

(await readdir('.', { withFileTypes: true })).filter(a =>
  a.name.endsWith('.js'),
)

但是,还是没有 shell 脚本简单:

ls *.js

为什么现有的 shell 无法在 JavaScript 中运行

bashsh 等这些 shell 工具已经存在几十年了。

但是,为什么它们在 JavaScript 中不能很好的工作?

macOS (zsh)Linux (bash)Windows (cmd) 的 shell 都有所不同,具有不同的语法和不同的命令。每个平台上可用的命令都不同,甚至相同的命令也可能有不同的可选参数和行为。

迄今为止,npm 的解决方案是依靠社区用 JavaScript 实现来填补缺失的命令。

rm -rf 不适用于 Windows

rimrafrm -rf 指令的跨平台实现,每周下载 6000 万次:

FOO=bar <script> 设置环境变量在 Windows 上不生效

不同平台上设置环境变量的方式略有不同。如果不使用 FOO=bar 这种方式,那就是使用 cross-env

which 在 Windows 上是 where

于是另一个周下载量 6000w 的包诞生了:

shell 启动时间也有一点长

创建一个 shell 执行需要多久?

在 Linux x64 Hetzner Arch Linux 机器上,大约需要 7ms:

$ hyperfine --warmup 3 'bash -c "echo hello"' 'sh -c "echo hello"' -N

Benchmark 1: bash -c 'echo hello'
  Time (mean ± σ):       7.3 ms ±   1.5 ms    [User: 5.1 ms, System: 1.9 ms]
  Range (min … max):     1.7 ms …   9.4 ms    529 runs

Benchmark 2: sh -c 'echo hello'
  Time (mean ± σ):       7.2 ms ±   1.6 ms    [User: 4.8 ms, System: 2.1 ms]
  Range (min … max):     1.5 ms …   9.6 ms    327 runs

如果只是想运行单个命令,但是启动 shell 可能比运行命令本身花费更长的时间。如果需要在循环中运行许多命令,那么成本就会升高。

你可以尝试嵌入 shell,但这样就复杂了,而且它们的许可证可能与你的项目不兼容。

这些 polyfill 真的必要吗?

在 2009 - 2016 年的里,JavaScript 还相对较新且处于实验阶段时,依靠社区来填补缺失的功能是很合理的。但现在已经是 2024 年了。JavaScript 已在广泛的使用于服务端开发了。如今,JavaScript 生态系统对需求的理解与 2009 年时完全不同了。

我们其实可以做得更好。

介绍一下 Bun Shell

Bun ShellBun 提供的一种新的实验性的嵌入式语言和解释器,支持使用 JavaScriptTypeScript 编写跨平台运行的 shell 脚本。

import { $ } from 'bun'

// 直接在终端里输出
await $`ls *.js`

// 转为字符串变量
const text = await $`ls *.js`.text()

同时允许你使用 JavaScript 变量:

import { $ } from 'bun'

const resp = await fetch('https://example.com')

const stdout = await $`gzip -c < ${resp}`.arrayBuffer()

出于安全问题考虑,所有模板变量都将被转义:

const filename = 'foo.js; rm -rf /'

// 将会执行指令 `ls 'foo.js; rm -rf /'`
const results = await $`ls ${filename}`

console.log(results.exitCode) // 1
console.log(results.stderr.toString()) // ls: cannot access 'foo.js; rm -rf /': No such file or directory

使用 Bun Shell 感觉就像普通的 JavaScript。允许你将标准输出放入 buffers 中:

import { $ } from 'bun'

const buffer = Buffer.alloc(1024)

await $`ls *.js > ${buffer}`

console.log(buffer.toString('utf8'))

你也可以将输出结果直接写入文件:

import { $, file } from 'bun'

// 当做文件输出
await $`ls *.js > ${file('output.txt')}`

// 或者文件路径字符串
await $`ls *.js > output.txt`
await $`ls *.js > ${'output.txt'}`

你还可以将输出结果通过管道运算符传递给其它命令:

import { $ } from 'bun'

await $`ls *.js | grep foo`

你甚至可以使用 Response 作为标准输入:

import { $ } from 'bun'

const buffer = new Response('bar\n foo\n bar\n foo\n')

await $`grep foo < ${buffer}`

可使用 cdechorm 等内置命令:

import { $ } from 'bun'

await $`cd .. && rm -rf node_modules/rimraf`

它可在 WindowsmacOSLinux 上运行。我们实现了许多常用命令和功能,如通配符环境变量重定向(redirection)管道(piping)等。

它被设计为简单 shell 脚本的替代品。在 WindowsBun 中,它将为 bun run 中的 package.json “脚本”提供支持。

为了更有趣一点,您还可以将它用作独立的 shell 脚本解释器:

echo "cat package.json" > script.bun.sh
bun script.bun.sh

如何安装?

Bun Shell 内置于 Bun 中。如果已经安装了 Bun v1.0.24 或更高版本,那么你就可以使用它:

bun --version
1.0.24

如果你没有安装Bun,可以使用curl安装:

curl -fsSL https://bun.sh/install | bash

或者使用 npm :

npm install -g bun

使用实践

创建 test.ts 文件,写入如下代码

import { $ } from 'bun'

await $`echo hello world`

const files = await $`ls *.js *.mjs`.text()

console.log(files.split('\n'))

运行脚本

bun test.ts

运行结果 如下

标签:脚本,Shell,await,js,shell,bun,ls,Bun
From: https://www.cnblogs.com/roseAT/p/17998022

相关文章

  • powershell param : 无法将“param”项识别为 cmdlet、函数、脚本文件或可运行程序的
    前言全局说明powershellparam:无法将“param”项识别为cmdlet、函数、脚本文件或可运行程序的名称。一、源码echo"脚本启动"param($age,$address="USA",$name)Write-Host"Name:$name"Write-Output"Address:$address"Write-Output"Age:$age&qu......
  • 今年接到一个根据excel来更新数据库的需求,用php写个小脚本
    需求大概内容是,excel中有些条目需要删除、有些需要新增,就需要基于这份excel生成删、增的SQL。要求是这样的:蓝色要删除的,黄色是要新增的,白色和灰色的不用管。我第一时间就在想:还得识别单元格颜色?excel长这样: 这种小需求用php来处理就很方便,用的框架是yii。发现读取到的只......
  • 【开源操作系统】上海道宁为您带来稳定、安全、开源和易用的操作系统——Ubuntu,为您的
    ​Ubuntu是源于非洲的一种传统价值观意为“人性、关爱和共享”这种价值观在开源、稳定、安全、易用的Ubuntu操作系统中得到了完美的体现  除此之外,Ubuntu还具有强大的安全性它自带了诸多安全功能如防火墙、加密文件系统等可以有效地保护用户的隐私和数据安全......
  • etcd v2 版本数据备份恢复脚本
    importrequestsimportjsonimportsysaction=sys.argv[1]etcdaddr=sys.argv[2]defbackup_data():url=f"{etcdaddr}/v2/keys/?recursive=true"response=requests.get(url)ifresponse.status_code==200:data=res......
  • Powershell 并发任务 | Runspace 线程 | 结果获取
    介绍在PowerShell中进行多任务处理(Multithreading或ParallelProcessing)主要目的是提高脚本的执行效率和性能。对于需要处理大量数据或执行多个独立任务的脚本来说尤其有用。提高性能:多任务处理允许脚本同时执行多个任务,从而加快整体执行速度。对于需要处理大型数据集或执......
  • 这些Shell分析服务器日志命令集锦,优秀!
    自己的小网站跑在阿里云的ECS上面,偶尔也去分析分析自己网站服务器日志,看看网站的访问量。看看有没有黑客搞破坏!于是收集,整理一些服务器日志分析命令,大家可以试试!1、查看有多少个IP访问:awk'{print$1}'log_file|sort|uniq|wc-l2、查看某一个页面被访问的次数:grep"/index.ph......
  • Shell 覆写文件以及追加内容方法
    平常开发时,在没有窗口的情况下,有时候调试看不到打印信息,就想把log写入一个临时文件中,但老是分不太清shell写入文件哪个是覆盖哪个是追加,这里记录一下。覆写文件内容需要将文件内容覆盖时,使用>指向目标文件追加文件内容需要在文件末尾追加内容时,使用>>指向目标文件代码......
  • Ubuntu安装tftp
    Ubuntu安装tftp服务器目录Ubuntu安装tftp服务器Ubuntu14.04Ubuntu16.04Ubuntu14.04安装:sudoapt-getinstalltftpd-hpatftp-hpa安装成功后,修改其配置文件/etc/default/tftpd-hpa,具体如下:TFTP_USERNAME="tftp"TFTP_DIRECTORY="/tftpboot/"TFTP_ADDRESS="0.0.0.0:6......
  • Unity5.x shader打包AssetBundle总结
    unity5.x  shader打包AssetBundle总结最近比较忙,好久没有更新博客了,新项目切换到unity5.x后使用了新的打包机制,在打包shader的时候遇到了一些问题,这里来记录一下吧。 在上一个项目中,我们使用unity4.7,对于shader并没有进行依赖打包,而是由unity打包到了每个用到的AssetBundle......
  • ubuntu18.04 局域网配置git server步骤
    1.安装ssh2.安装gitsudoapt-getupdatesudoaptinstallvimsudoaptinstallopenssh-serversudoaptinstallgit3.cdhome目录mkdircodecdcodegitinit--baretest.git#创建git-server仓库远程服务器远程地址:/home/joker/code/test.git4.本地电脑目录操作......