一文学会搭建 cli 脚手架工具

文章目录

  • 设置工具命令
    • package.json bin 字段
    • 注释:#!/usr/bin/env node
    • 设置环境变量
  • 接收命令选项参数
    • process 实现
    • commander
  • 命令行交互:inquirer
  • 下载项目模板:download-git-repo
  • 执行额外命令:自动安装依赖
    • child_process
    • execa
  • 体验优化
    • 输出彩色信息:chalk
    • loading 加载状态提示:ora
    • 控制台输出表格:easy-table
    • 控制台输出方框:boxen
    • 输出 ASCII 的艺术字体:figlet

通过学习搭建脚手架工具,学习 nodejs 开发命令行工具知识。

设置工具命令

以 create-vite 为例,怎么终端就能识别 create-vite 为一个命令呢?并且会执行一些逻辑呢?这些逻辑代码写在哪?

  • 通过 bin 字段。

package.json bin 字段

bin 字段用来设置内部命令,并且指定命令对应的执行文件。

设置一个命令为 ikun,命令行执行 ikun 其实就是执行 main.js 文件。

{
  "bin": {
    "ikun": "./src/main.js"
  }
}

注释:#!/usr/bin/env node

#!/usr/bin/env node 是一个称为 shebang(或 hashbang)的特殊注释,它出现在脚本文件的第一行。这个注释的作用是告诉 Unix 或类 Unix 系统的操作系统,当用户尝试执行这个脚本时,应该使用哪个解释器来运行这个脚本。

在这个例子中,#!/usr/bin/env node 指示系统使用 env 命令来查找 node 解释器,并使用 node 来执行该脚本。env 命令会在系统的环境变量中查找 node 可执行文件,这样可以确保无论 node 安装在哪个目录下,脚本都能正确地运行。

#!/usr/bin/env node

console.log(234);

设置环境变量

学过 Java 都知道,第一步就是设置环境变量,没有设置环境变量,是不能在任意路径下使用 java 命令的。

我们的 ikun 命令自然也是一样的,也需要添加入环境变量。

如果这个包npm publish发布后,用户npm install安装这个包。package.json 中有 bin 字段,就会自动添加入环境变量。用户可直接使用 ikun 命令。

那我们在开发的时候怎么办?
可以使用npm link给这个命令建立一个软连接,连接到全局。这样我们就能像全局安装了这个包一样,能全局直接用了。

# 建立连接
npm link --global

# 断开连接,也是全局删除这个包
npm unlink cli-demo --global

npm uninstall 文档中可以发现,unlink 其实是 uninstall 的别名,实质上也是删除了包。

pnpm link | pnpm中文文档 | pnpm中文网
pnpm unlink | pnpm中文文档 | pnpm中文网

# 建立连接
pnpm link --global

# 断开连接(其实就是全局卸载这个包)
pnpm uninstall --global cli-demo

接收命令选项参数

命令通常可以接收一些选项参数 options。比如几乎所有命令都有的一个版本。

  • java --version

并且选项还可以添加一些参数,如 git 提交 -m 选项后填写参数,作为提交说明:

  • git add -m "第一次提交"

我们的 ikun 命令怎么实现这个?

  • 原生实现
  • 第三方库:commander

process 实现

process 全局对象

#!/usr/bin/env node
const package = require("../package.json");

const option = process.argv[2];

if (option === "-v" || option === "--version") {
    // package.json 会自动解析为 js 对象
    console.log(package.version);
}

CommonJS 能直接解析 JSON 文件,但是 ESM 不可以,目前只是实验性支持:断言类型为 JSON

import packageModule from "../../package.json" assert { type: "json" };

import("../../package.json", { assert: { type: "json" } })
 .then(({ default: packageModule }) => {});

(node:8072) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time

因此 node 中处理 JSON 文件,最好的办法还是通过 fs 模块 IO 将 JSON 文件内容读取为字符串,然后 JSON.parse。

import fs from "fs";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";

const packageJsonUrl =  resolve(dirname(fileURLToPath(import.meta.url)), "../../package.json"))
const packageJsonStr = fs.readFileSync(packageJsonUrl, "utf-8");
const packageModule = JSON.parse(packageJsonStr);

这样原生是可以实现,但是太麻烦了。

commander

commander

实现类似 vue-cli 的效果:
命令行输入ikun create 项目名,就会在该目录下生成一个 vue 项目模板。

const { program } = require('commander')

function helpOptions() {
  // 1.处理--version的操作
  const version = require('../../package.json').version
  program.version(version, '-v --version')

  // 2.增强其他的options的操作
  program.option('-w --why', "a why cli program~")
  program.option('-d --dest <dest>', 'a destination folder, 例如: -d src/components')

  program.on('--help', () => {
    console.log("")
    console.log("others:")
    console.log("  xxx")
    console.log("  yyy")
  })
}

module.exports = helpOptions

const { program } = require('commander')
const { createProjectAction, addComponentAction } = require('./core/actions')
const helpOptions = require('./core/help-options')

// 1.配置所有的options
helpOptions()

// 2.增加子命令实现具体功能
program
  .command("create <project> [...others]")
  .description("create vue project into a folder, 比如: whycli create airbnb")
  .action(createProjectAction)

program
  .command("addcpn <cpnname> [...others]")
  .description("add vue component into a folder, 比如: whycli addcpn NavBar -d src/components")
  .action(addComponentAction)

// 让commander解析process.argv参数
program.parse(process.argv)

命令行交互:inquirer

命令行交互,比如执行命令后,一问一答询问你项目名要填什么,是否要支持 ts 等等。

inquirer 、enquirer、prompts。这三个库都可以处理复杂的用户输入,完成命令行输入交互。

Inquirer 是一个强大的命令行交互工具,用于与用户进行交互和收集信息。它提供了各种丰富的交互式提示(如输入框、选择列表、确认框等),可以帮助你构建灵活的命令行界面。通过 Inquirer,你可以向用户提出问题,获取用户的输入,并根据用户的回答采取相应的操作。

Inquirer.js 提供了一系列的预设问题类型,包括:

  • 输入(Input):让用户输入一些文本。
  • 确认(Confirm):让用户回答是或否的问题。
  • 列表(List):让用户从列表中选择一个选项。
  • 检查框(Checkbox):让用户从多个选项中选择多个。
  • 扩展列表(Expand):让用户通过键盘快捷键从多个选项中选择一个。
  • 密码(Password):让用户输入密码,输入时字符会被隐藏。

以下是一个使用 Inquirer.js 的简单示例:
在这个示例中,Inquirer.js 会依次显示三个问题,并根据用户的回答存储在 answers 对象中。

import inquirer from "inquirer";

async function promptQuestions() {
    let answers;
    try {
        answers = await inquirer.prompt([
            // ... questions
            {
                type: "input",
                name: "username",
                message: "请输入您的用户名:"
            },
            {
                type: "confirm",
                name: "isVIP",
                message: "您是VIP用户吗?",
                default: false
            },
            {
                type: "list",
                name: "plan",
                message: "请选择您的计划:",
                choices: ["Free", "Professional", "Enterprise"],
                filter: function (val) {
                    return val.toLowerCase();
                }
            }
        ]);

        console.log(JSON.stringify(answers, null, "  "));
    } catch (error) {
        if (error.isTtyError) {
            console.log("Prompt couldn't be rendered in the current environment");
        } else {
            console.log("Something else went wrong");
        }
    }

    return answers;
}

export default promptQuestions;

// {
//   "username": "hh",
//   "isVIP": false,
//   "plan": "professional"
// }

下载项目模板:download-git-repo

本地生成的 vue 项目模块其实 glt clone 下来的,并不是本地生成的。这样的好处就是,模板在 github 上,我可以实时更新,但是命令行工具代码不用变。

去 github clone 项目的操作没必要自己实现,使用第三方库即可。

Phillip Lanclos / download-git-repo · GitLab

Download-git-repo 是一个用于下载 Git 仓库的 npm 库。它提供了一个简单的接口,可以方便地从远程 Git 仓库中下载项目代码。你可以指定要下载的仓库和目标目录,并可选择指定分支或标签。Download-git-repo 支持从各种 Git 托管平台(如 GitHub、GitLab、Bitbucket 等)下载代码。

download-git-repo

const VUE_REPO = "direct:https://github.com/coderwhy/vue3_template.git#main"

module.exports = {
  VUE_REPO
}
async function createProjectAction(project) {
  try {
      // 1.从编写的项目模板中clone下来项目
      await download(VUE_REPO, project, { clone: true })

      // 2. 模板下载好后,给予一些提示,比如进入项目,下载依赖等
      console.log(`cd ${project}`)
      console.log(`npm install`)
      console.log(`npm run dev`)
    
    } catch (error) {
      console.log("github连接失败, 请稍后重试")
  }
}

执行额外命令:自动安装依赖

下载好项目模板后,可以继续帮用户自动执行npm install下载好依赖。

当前 node 主线程正在执行我们的 ikun 命令,此时又要执行 npm 命令。因此我们需要在 node 中开一个子进程。

https://www.yuque.com/ahcheng123/project/dbhhnl6sxm7zgwmw#Ym8tS

child_process

子进程 childProcess

const { spawn } = require('child_process')

function execCommand(...args) {
  return new Promise((resolve) => {
    // npm install/npm run dev
    // 1.开启子进程执行命令
    const childProcess = spawn(...args)

    // 2.获取子进程的输出和错误信息
    childProcess.stdout.pipe(process.stdout)
    childProcess.stderr.pipe(process.stderr)

    // 3.监听子进程执行结束, 关闭掉
    childProcess.on('close', () => {
      resolve()
    })
  })
}

module.exports = execCommand

要执行 npm 命令要注意,不同平台执行的实际命令不同。

  • win:npm.cmd
  • mac: npm
  • linux: npm
async function createProjectAction(project) {
  try {
    // 1.从编写的项目模板中clone下来项目
    await download(VUE_REPO, project, { clone: true })

    // 2.很多的脚手架, 都是在这里给予提示

    // 3.帮助执行npm install
    console.log(process.platform)
    const commandName = process.platform === 'win32'? 'npm.cmd': 'npm'
    await execCommand(commandName, ["install"], { cwd: `./${project}` })

    // 4.帮助执行npm run dev
    await execCommand(commandName, ["run", "dev"], { cwd: `./${project}` })
  } catch (error) {
    console.log("github连接失败, 请稍后重试")
  }
}

至此,其实一个 cli 工具的主体功能基本完成了。

execa

https://github.com/sindresorhus/execa?tab=readme-ov-file

Execa 是一个流行的 Node.js 库,它提供了一种更简单、更现代的方式来执行子进程。它对 Node.js 原生的 child_process 模块进行了封装,提供了一系列的改进和额外功能,使得执行外部命令更加方便和可靠。

Execa 的主要特点包括:

  1. 清晰的 API:Execa 提供了简洁明了的 API,使得执行命令和获取输出变得更加简单。
  2. 跨平台支持:它能够在不同的操作系统上提供一致的表现,例如在 Windows 上正确处理路径和扩展名。
  3. 流式输出:Execa 支持流式输出,这意味着你可以实时地获取命令的输出,而不是等到命令执行完毕后一次性获取。
  4. Promise-based:Execa 使用 Promise,使得异步操作更加易于管理和组合。
  5. 改进的错误处理:它能够提供更详细的错误信息,包括命令的退出码和信号。
  6. 同步模式:除了默认的异步模式外,Execa 还支持同步执行命令。
    以下是一个使用 Execa 执行命令的简单示例:

Execa 支持交互式命令,你可以使用 stdio: ‘inherit’ 将子进程的输入/输出/错误传递给父进程:

const execa = require('execa');

async function runInteractiveCommand() {
  try {
    await execa('git', ['commit'], { stdio: 'inherit' });
  } catch (error) {
    console.error('命令执行出错:', error);
  }
}

runInteractiveCommand();

Execa 是许多现代 Node.js 应用程序的流行选择,特别是那些需要频繁与系统命令交互的应用程序,例如构建工具、测试框架和开发工具等。

import { execa } from "execa";

/**
 * 执行命令
 * @param {string} command — The program/script to execute.
 * @param {string[]} args — Arguments to pass to file on execution.
 * @param {*} options
 */
export async function execCommand(command, args) {
    try {
        await execa(command, args, { stdio: "inherit" });
    } catch (error) {
        console.log("error", error);
    }
}

体验优化

输出彩色信息:chalk

  • https://github.com/chalk/chalk

使用 console.log 输出提示信息太丑了,使用第三方库 chalk 可以输出彩色的控制台信息。

搭建 ts koa 项目模板

import chalk from "chalk";

// 定义主题和对应的 emoji
const theme = {
    info: { color: chalk.blue, emoji: " 💡 " },
    success: { color: chalk.green, emoji: " 🎉 " },
    warning: { color: chalk.yellow, emoji: " 🔔 " },
    error: { color: chalk.red, emoji: " 🚨 " },
    debug: { color: chalk.gray, emoji: " 🔍 " },
    highlight: { color: chalk.bold, emoji: " 🌟 " }
};

// 日志工具方法
const logInfo = message => console.log(`${theme.info.emoji}${theme.info.color(message)}`);
const logSuccess = message => console.log(`${theme.success.emoji}${theme.success.color(message)}`);
const logWarning = message => console.log(`${theme.warning.emoji}${theme.warning.color(message)}`);
const logError = message => console.log(`${theme.error.emoji}${theme.error.color(message)}`);
const logDebug = message => console.log(`${theme.debug.emoji}${theme.debug.color(message)}`);
const logHighlight = message => console.log(`${theme.highlight.emoji}${theme.highlight.color(message)}`);

// 导出方法
export { logInfo, logSuccess, logWarning, logError, logDebug, logHighlight };

loading 加载状态提示:ora

  • https://github.com/sindresorhus/ora

Ora 是一个用于在命令行界面显示加载动画的 npm 库。它可以帮助你在执行耗时的任务时提供一个友好的加载状态提示。Ora 提供了一系列自定义的加载动画,如旋转器、进度条等,你可以根据需要选择合适的加载动画效果,并在任务执行期间显示对应的加载状态。

在这里插入图片描述

控制台输出表格:easy-table

  • https://github.com/eldargab/easy-table
var Table = require('easy-table')

var data = [
  { id: 123123, desc: 'Something awesome', price: 1000.00 },
  { id: 245452, desc: 'Very interesting book', price: 11.45},
  { id: 232323, desc: 'Yet another product', price: 555.55 }
]

var t = new Table

data.forEach(function(product) {
  t.cell('Product Id', product.id)
  t.cell('Description', product.desc)
  t.cell('Price, USD', product.price, Table.number(2))
  t.newRow()
})

console.log(t.toString())
Product Id  Description            Price, USD
----------  ---------------------  ----------
123123      Something awesome         1000.00
245452      Very interesting book       11.45
232323      Yet another product        555.55

控制台输出方框:boxen

  • https://github.com/sindresorhus/boxen

Boxen 是一个轻量级的 Node.js 库,用于将文本内容格式化为带框的文本,通常用于美化命令行输出。它可以将文本包裹在固定的宽度中,并在文本周围添加边框,使得输出更加整洁和易于阅读。
使用 Boxen,你可以轻松地创建各种形状和大小的框,包括单行和多行的文本。Boxen 支持多种边框样式,并且可以根据需要调整边框、填充和间距等样式属性。

import boxen from 'boxen';

console.log(boxen('unicorn', {padding: 1}));
/*
┌─────────────┐
│             │
│   unicorn   │
│             │
└─────────────┘
*/

console.log(boxen('unicorn', {padding: 1, margin: 1, borderStyle: 'double'}));
/*

   ╔═════════════╗
   ║             ║
   ║   unicorn   ║
   ║             ║
   ╚═════════════╝

*/

console.log(boxen('unicorns love rainbows', {title: 'magical', titleAlignment: 'center'}));
/*
┌────── magical ───────┐
│unicorns love rainbows│
└──────────────────────┘
*/

输出 ASCII 的艺术字体:figlet

  • https://github.com/patorjk/figlet.js

很多库都有这样的标题,比如 spring。

figlet.text(
  "Boo!",
  {
    font: "Ghost",
    horizontalLayout: "default",
    verticalLayout: "default",
    width: 80,
    whitespaceBreak: true,
  },
  function (err, data) {
    if (err) {
      console.log("Something went wrong...");
      console.dir(err);
      return;
    }
    console.log(data);
  }
);
.-. .-')                            ,---.
\  ( OO )                           |   |
 ;-----.\  .-'),-----.  .-'),-----. |   |
 | .-.  | ( OO'  .-.  '( OO'  .-.  '|   |
 | '-' /_)/   |  | |  |/   |  | |  ||   |
 | .-. `. \_) |  |\|  |\_) |  |\|  ||  .'
 | |  \  |  \ |  | |  |  \ |  | |  |`--'
 | '--'  /   `'  '-'  '   `'  '-'  '.--.
 `------'      `-----'      `-----' '--'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/441614.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FineReport决策报表Excel导出数据不全解决办法

一、首先建立决策报表 决策报表不带参数导出办法&#xff08;即没有参数面板&#xff09; 普通决策报表导出&#xff08;没有搜索面板&#xff09; 如果决策报表带参数&#xff08;即有搜索框&#xff09;&#xff0c;用上面的办法只能导出部分数据&#xff0c;数据不全 二、…

Go语言框架路由Controller控制器设计思路gin路由根据控制器目录分层生成路由地址

Controller设计好处 框架设计用controller分请求路由层级&#xff0c;应用从app目录开始对应请求url路由地址&#xff0c;这样设计师方便开发时候通过请求地址层级快速定位接口方法对应的代码位置。 例如api接口请求路径为&#xff1a;​​http://localhost:8110/​​busines…

C.C语言分支和循环语句

文章目录 一. 什么是语句 二. 分支语句&#xff08;选择结构&#xff09; 2.1. if 语句 2.1.1. 语法结构 2.1.2. 悬空else 2.1.3. 书写形式的对比 2.1.4. 练习 2.2. switch 语句 3.2.1. 语法结构 3.2.2. 在switch语句中的 break 3.2.3. default子句 3.2.4. 练习 三…

打造你的贪吃蛇游戏:HTML、CSS与JavaScript的完美结合

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

IPSEC VPPN实验

实验背景&#xff1a;FW1和FW2是双机热备的状态。 实验要求&#xff1a;在FW和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置&#xff08;由于是双机热备状态&#xff0c;所以FW1和FW2只需要配置FW1主设备即可&…

portainer管理远程docker和docker-swarm集群

使用前请先安装docker和docker-compose&#xff0c;同时完成docker-swarm集群初始化 一、portainer-ce部署 部署portainer-ce实时管理本机docker&#xff0c;使用docker-compose一键拉起 docker-compose.yml version: 3 services:portainer:container_name: portainer#imag…

Java高频面试之消息队列与分布式篇

有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 消息队列的基本作用&#xff1f; 异步通信&#xff1a;消息队列提供了异步通信的能力&#xff0c;发送方可以将消息发送到队列中&#xff0c;而无需等待接收方立即处理。发送方和接收方可以解耦&#x…

【数据结构】单链表的层层实现!! !

关注小庄 顿顿解馋(●’◡’●) 上篇回顾 我们上篇学习了本质为数组的数据结构—顺序表&#xff0c;顺序表支持下标随机访问而且高速缓存命中率高&#xff0c;然而可能造成空间的浪费&#xff0c;同时增加数据时多次移动会造成效率低下&#xff0c;那有什么解决之法呢&#xff…

Matlab|2机5节点牛拉法(含报告)

目录 主要内容 下载链接 主要内容 采用牛拉法计算2机5节点的潮流计算程序&#xff0c;程序迭代稳定&#xff0c;运行可靠&#xff0c;含报告资料。 下载链接

pytorch的梯度图与autograd.grad和二阶求导

前向与反向 这里我们从 一次计算 开始比如 zf(x,y) 讨论若我们把任意对于tensor的计算都看为函数&#xff08;如将 a*b&#xff08;数值&#xff09; 看为 mul(a,b)&#xff09;&#xff0c;那么都可以将其看为2个过程&#xff1a;forward-前向&#xff0c;backward-反向在pyto…

【Web】浅聊Java反序列化之C3P0——JNDI注入利用

目录 简介 原理分析 EXP 前文&#xff1a;【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下&#xff0c;这个C3P0的Gadget可以和fastjson&#xff0c;Snake YAML , JYAML,Yamlbeans , …

【Javascript编程实操05】1、小明买洗发水、香皂、牙刷组合 2、利用循环写出100以内的奇数的和及偶数的和

前言 1、小明买洗发水、香皂、牙刷组合 代码&#xff1a; 实现效果&#xff1a; 2、利用循环写出100以内的奇数的和及偶数的和 代码&#xff1a; 实现效果&#xff1a; 总结 前言 本次主要是继续针对Javascript阶段的for循环的实操练习&#xff0c;共有2个实操&#xff…

vscode setting.json 全局设置 工作区设置 位置 优先级

vscode中setting.json有两种配置权限 一、全局配置&#xff1a;setting.json文件位于C:\Users\Administrator\AppData\Roaming\Code\User\settings.json 二、工作区配置&#xff1a;setting.json文件位于工作区的.vscode\settings.json 当两种配置同时存在时&#xff0c;工作区…

单链表详解(如何实现单链表)

文章目录 前言 一、单链表是什么&#xff1f;二、单链表的实现总结 顺序表的缺点 1.中间/头部的插入删除&#xff0c;时间复杂度为O (N) 2.realloc 扩容&#xff08;特别是异地扩&#xff0c;需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间&#xff09;会有不小的…

【开源】JAVA+Vue.js实现高校宿舍调配管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统展示四、核心代码4.1 查询单条个人习惯4.2 查询我的室友4.3 查询宿舍4.4 查询指定性别全部宿舍4.5 初次分配宿舍 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的…

Day24:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

目录 文件管理模块-上传-过滤机制 文件管理模块-显示-过滤机制 思维导图 PHP知识点 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技术&#xff1a;输入输出&#…

泛微OA服务器获取 token

泛微OA服务器获取 token 文章目录 泛微OA服务器获取 token一、泛微官方方法1 ecology 系统配置2 发放/生成许可证(appid)3 限制许可证使用ip地址&#xff08;该步骤也可以跳过&#xff09;4 使用 postman 注册5 获取 token6 访问业务系统接口 二、java 代码获取 token三、封装到…

【Redis项目实战】使用Springcloud整合Redis分布式锁+RabbitMQ技术实现高并发预约管理处理系统

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Redis实战与进阶》 本专栏带你Redis从入门到入魔 这是苏泽的个…

一次生产环境上的dockerd启动失败原因分析

今夜原计划对 生产环境 上的 SDN 组件进行一次紧急扩容操作的&#xff0c;但业务基础环境中的 Docker-Engine 启动不起来了、原定计划也就无法继续进行了。 尽管查清了基础业务环境中的故障原因&#xff0c;但金主DD说今天先不干了&#xff0c;那就整理整理思路写篇流水账吧 。…

Linux环境下使用线程方式操作UART读写功能

目录 概述 1 Linux环境下UART设备 2 轮询方式操作UART功能实现 2.1 打开串口函数&#xff1a;usr_serial_open 2.2 关闭串口函数&#xff1a; usr_serial_close 2.3 发送数据函数&#xff1a; usr_serial_sendbytes 2.4 接收数据函数&#xff1a; thread_uart_readbytes …