MoreRSS

site iconLuffy | 沈唁志修改

分享 PHP、Swoole 技术资源、实用插件、有趣网站和 WordPress 相关内容。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Luffy | 沈唁志的 RSS 预览

使用 GitHub Actions 自动同步 Docker 镜像到 CNB

2025-08-04 15:47:30

为了提升访问速度、增强稳定性并规避部分官方源的不确定性,将常用的开源镜像同步到中国大陆可访问的镜像仓库是一种高效的解决方案。

本文介绍如何通过 GitHub Actions 自动化完成该同步流程,支持选择性构建与定制版本。

背景

许多开源镜像托管在 Docker Hub 上,但由于网络、访问频率限制等问题,拉取速度不稳定,甚至存在连接失败的情况。

之前是使用 GitHub Actions 同步到 CODING 上,不过要 CODING 要停服了,所以改为同步到 CNB 了。

cnb.cool 也是由腾讯出品,基于 Docker 生态,对环境、缓存、插件进行抽象,通过声明式的语法,帮助开发者以更酷的方式构建软件。

支持代码托管、云原生构建和云原生开发等功能。

同步方案概览

  • 镜像列表维护在 .github/images.yml 中;
  • 手动或自动触发 GitHub Actions;
  • 使用 skopeo 工具将镜像从 Docker Hub 同步到 CNB;
  • 支持选择同步特定镜像或全部镜像;
  • 支持指定版本(tag)。

GitHub Actions 工作流详解


点击查看完整文件内容

前往 GitHub 查看:docker-proxy.yml

name: Mirror Docker Images to CNB

on:
  workflow_dispatch:
    inputs:
      name:
        description: 'Select image to mirror (or leave blank to mirror all)'
        required: false
        type: choice
        options:
          - ""
          - vaultwarden
          - bark-server
          - elasticsearch
          - mysql
          - hyperf
          - clickhouse
      version:
        description: 'Override tag version'
        required: false
        type: string
  push:
    paths:
      - '.github/images.yml'
    branches: [ 'main' ]

jobs:
  mirror:
    name: >-
      Mirror ${{ github.event.inputs.name || 'All Images' }}${{ github.event.inputs.version && format(' (version: {0})', github.event.inputs.version) || '' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Mirror images
        env:
          INPUT_NAME: ${{ github.event.inputs.name }}
          INPUT_VERSION: ${{ github.event.inputs.version }}
        run: |
          images=$(yq -o json '.images' ${{ github.workspace }}/.github/images.yml)

          if [ -n "$INPUT_NAME" ]; then
          matrix=$(echo "$images" | jq -c --arg name "$INPUT_NAME" '.[] | select(.name == $name)')
          else
          matrix=$(echo "$images" | jq -c '.[]')
          fi

          if [ -z "$matrix" ]; then
          echo "No matching images found for name: $INPUT_NAME"
          exit 1
          fi

          echo "$matrix" | while read -r item; do
            image=$(echo "$item" | jq -r '.image')
            name=$(echo "$item" | jq -r '.name')
            default_tag=$(echo "$item" | jq -r '.tag')
            tag=${INPUT_VERSION:-$default_tag}

            echo "Mirroring $image:$tag to docker.cnb.cool/lufei/docker/$name:$tag"

            skopeo copy --all docker://docker.io/${image}:${tag} \
              docker://docker.cnb.cool/lufei/docker/${name}:${tag} \
              --src-creds "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" \
              --dest-creds "cnb:${{ secrets.CNB_DOCKER_TOKEN }}"

            echo "::notice title=Image Published::https://docker.cnb.cool/lufei/docker/${name}:${tag}"
          done

触发机制

on:
  workflow_dispatch:
    inputs:
      name:     # 可选镜像名
      version:  # 可选覆盖 tag
  push:
    paths:
      - '.github/images.yml'
    branches: [ 'main' ]

支持两种触发方式:

  1. 手动触发:可选择特定镜像名和版本;
  2. 自动触发:当 .github/images.yml 文件变更时,自动同步全量更新。

镜像清单文件

.github/images.yml

images:
  - image: "vaultwarden/server"
    tag: "latest"
    name: "vaultwarden"
  - image: "finab/bark-server"
    tag: "latest"
    name: "bark-server"
  ...

核心同步逻辑

skopeo copy --all docker://docker.io/${image}:${tag} \
  docker://docker.cnb.cool/lufei/docker/${name}:${tag} \
  --src-creds "${{ secrets.DOCKERHUB_USERNAME }}:${{ secrets.DOCKERHUB_TOKEN }}" \
  --dest-creds "cnb:${{ secrets.CNB_DOCKER_TOKEN }}"
  • --all:确保同步多平台镜像(如 amd64 和 arm64);
  • 使用 GitHub Secrets 配置凭据;
  • 输出同步完成后可直接拉取的地址提示。

如何使用

1. 手动触发

在 GitHub → Actions → “Mirror Docker Images to CNB” → 点击 “Run workflow”:

选择镜像

  • 留空镜像名 → 同步所有;
  • 指定镜像名 → 同步该镜像;
  • 同时指定 tag → 覆盖默认 tag。

指定tag

2. 自动触发

每次更新 .github/images.yml 文件并推送到 main 分支时,会自动同步所有的镜像。

镜像拉取示例

同步完成后,用户可直接通过 CNB 公网地址拉取镜像:

docker pull docker.cnb.cool/lufei/docker/hyperf:8.3-alpine-v3.21-swoole

加上https://可以访问网页查看详情:

输出可以访问的镜像链接

安全配置(GitHub Secrets)

名称 用途说明
DOCKERHUB_USERNAME 用于拉取源镜像
DOCKERHUB_TOKEN Docker Hub 登录 token
CNB_DOCKER_TOKEN CNB 镜像仓库推送凭据

CNB 默认可以创建 npm、Composer 等的制品库,但 Docker 的制品默认就在仓库中,所以创建一个仓库即可。

总结

通过 GitHub Actions + skopeo + CNB 服务,我们构建了一个可复用、自动化、支持多镜像同步的工具链,显著提升了镜像的可用性与部署效率。

怎么申请开具中国税收居民身份证明?

2025-04-18 17:04:42

之前因为 Google Adsense 要求进行新加坡税务信息填写,需要上传税务证明,但是实在找不到个人在哪里申请,于是就暂停了 Google Adsense 服务。

不过在 2025 年 4 月 1 日起施行了新规,申请《中国税收居民身份证明》不再困难了!

下面就来说说申请步骤:

  1. 访问自然人电子税务局官网,找到我要办税,点击中国税收居民身份证明开具

自然人电子税务局官网

  1. 点击申请开具《中国税收居民身份证明》。后续查询也是这里,点击旁边的查询。

申请开具《中国税收居民身份证明》

  1. 选择申请年度等信息,选择完成后下一步会要求你确认主管税务机关,这个是根据任职受雇单位自动匹配,只需要选择使用那个单位申报就可以。

选择申请年度

  1. 填写申请信息,这里的要求比较多,我下文直接提供了

填写申请信息

  • 对方纳税人名称:Google Asia Pacific Pte. Ltd.
  • 拟适用协定名称:中华人民共和国政府和新加坡共和国关于对所得避免双重征税和防止偷漏税的协定
  • 拟适用协定条款:独立个人劳务条款
  • 拟享受协定待遇收入金额(元):按实际填,比如 720
  • 预计减免税金额(元):按实际填,比如 72
  • 相关附件:使用 Google AdSense 的在线服务条款即可,从这里下载:AdSense 在线服务条款
  • 申请人信息会自动补全
  • 在中国境内是否有住所:是
  • 有住所个人提供因户籍、家庭、经济利益关系而在中国境内习惯性居住的证明材料或说明材料:多选,可以选户籍或者经济利益关系,选择后需要上传身份证、户口簿,我还补充了自己公司的营业执照

在中国境内是否有住所填写

  • 证明领取方式:电子领取

点击下一步提交确认等待主管机关审核即可。

审核通过后没有通知,需要自己去登录网站去查看,如果有问题的话,可能会被拒绝,或者主管机关会给你打电话。

目前我已经通过了,1 号政策开放的时候提交了一次,前几天主管机关下级给我打电话说没有下发成功,让我撤销重新提交一次,这次提交后两三天就通过了。

HMAC 签名编码的坑:Go 和 PHP 的不同处理方式

2025-03-06 17:19:07

在开发过程中,我们经常使用 HMAC(散列消息认证码)对数据进行签名,以确保数据完整性和身份验证。

然而,不同编程语言在对签名数据进行编码时可能会有所不同,导致相同的 HMAC 计算在不同语言中产生不同的结果。

这篇文章也是因为我直接将 PHP 的签名算法扔给 ChatGPT 生成,并没有实际测试,导致客户反馈签名计算失败,测试后才发现的。

本文将以 Go 和 PHP 为例,探讨为什么直接对 HMAC 签名进行 Base64 编码与先转换为 16 进制字符串再编码的结果不同。

代码示例

Go 代码

package main

import (
    "crypto/hmac"
    "crypto/sha1"
    "encoding/base64"
    "encoding/hex"
    "fmt"
)

func main() {
    data := "hello"
    password := "123456"
    h := hmac.New(sha1.New, []byte(password))
    h.Write([]byte(data))
    signatureBytes := h.Sum(nil)

    // 直接对 HMAC 结果进行 Base64 编码
    base64Signature := base64.StdEncoding.EncodeToString(signatureBytes)
    fmt.Println(base64Signature) // 输出:NYSQUfYBHG0EZ6pU+r+Iw4CvPIQ=

    // 先转换成 16 进制字符串,再进行 Base64 编码
    hexString := hex.EncodeToString(signatureBytes)
    base64OfHex := base64.StdEncoding.EncodeToString([]byte(hexString))
    fmt.Println(base64OfHex) // 输出:MzU4NDkwNTFmNjAxMWM2ZDA0NjdhYTU0ZmFiZjg4YzM4MGFmM2M4NA==
}

PHP 代码

<?php
$data = "hello";
$password = "123456";

// 直接对 HMAC 结果进行 Base64 编码
echo base64_encode(hash_hmac('sha1', $data, $password, true));
// 输出:NYSQUfYBHG0EZ6pU+r+Iw4CvPIQ=

echo "\n";

// 先转换成 16 进制字符串,再进行 Base64 编码
echo base64_encode(hash_hmac('sha1', $data, $password));
// 输出:MzU4NDkwNTFmNjAxMWM2ZDA0NjdhYTU0ZmFiZjg4YzM4MGFmM2M4NA==
?>

为什么结果不同?

表面上看,Go 和 PHP 代码的逻辑是相同的,但它们的 Base64 结果却不同。

其根本原因在于编码前的输入数据不同。

PHP 参数定义文档

hash_hmac(
    string $algo,
    string $data,
    #[\SensitiveParameter] string $key,
    bool $binary = false
): string

PHP 手册中也提到了:当 binary 设置为 true 输出原始二进制数据,设置为 false 输出小写 16 进制字符串。

原始二进制 vs. 16 进制字符串

  1. 原始二进制数据
    • 在 Go 代码中,signatureBytes 是 HMAC 计算出的二进制数据。
    • 在 PHP 代码中,hash_hmac('sha1', $data, $password, true) 也返回二进制数据。
    • 直接对这些二进制数据进行 Base64 编码,输出的是编码后的 HMAC 结果。
  2. 16 进制字符串转换
    • 在 PHP 中,hash_hmac('sha1', $data, $password) 默认返回 16 进制字符串,每个字节被转换成 2 个字符。
    • 在 Go 中,hex.EncodeToString(signatureBytes) 也会将二进制数据转换为 16 进制字符串。
    • 由于 16 进制字符串的长度是原始二进制数据的 2 倍,在进行 Base64 编码时,最终结果也会完全不同。

Base64 编码的作用

Base64 编码的主要作用是将二进制数据转换为文本格式,便于在 URL 或 JSON 等环境中传输。

它不会改变数据的内容,而是按照固定的方式将每 3 个字节转换为 4 个可打印字符。

因此,输入数据的不同会直接影响最终的编码结果。

如何保证一致性?

如果希望跨语言 HMAC 计算保持一致,建议:

  • 确保 Base64 编码前的数据格式一致,统一使用二进制数据进行编码。
  • 在 PHP 中,使用 hash_hmac('sha1', $data, $password, true) 以获取二进制结果。
  • 在 Go 中,直接使用 base64.StdEncoding.EncodeToString(signatureBytes),避免中间转换为 16 进制字符串。

结论

  • 直接对 HMAC 结果进行 Base64 编码,能保持原始数据格式,保证数据可还原。
  • 先转换为 16 进制字符串再进行 Base64 编码,会导致数据翻倍,最终的编码结果不同。
  • 在不同语言间使用 HMAC 签名时,务必保证编码方式的一致性,以避免验证失败。

希望这篇文章能帮助你理解 HMAC 签名在不同语言中的编码差异,并在开发中避免类似的问题!

Bitwarden Secrets Manager:简化 DevOps 的机密管理

2025-02-27 14:42:30

在 DevOps 和开发流程中,如何安全高效地管理机密数据(如密码、API 密钥和认证信息)是一个重要话题。

Bitwarden 是一款开源密码管理工具,帮助用户存储、管理并共享敏感信息。Bitwarden 推出了新产品Secrets Manager,专为 DevOps 团队和开发人员提供简化的机密管理方案。

对于使用 GitHub Actions 等 CI/CD 工具的团队来说,Secrets 是一种存储机密信息的常见方式。

但是,GitHub Actions 中的 Secrets 一旦保存,就无法查看或修改,这使得本地保存机密变得繁琐且易出错。

而在团队环境中,个人和公司电脑之间的同步问题更是增加了额外的复杂性。

Bitwarden Secrets Manager 解决了这一难题,提供了安全、高效的机密存储与管理方式。

免费额度和在线服务

与传统的 Bitwarden 密码管理器类似,Secrets Manager 也支持 self-hosting,但需要授权才能进行。

为了简化流程(白嫖),也可以使用 Bitwarden 提供的在线服务,享受如下免费额度:

  • 无限量的 Secrets
  • 2 位用户
  • 3 个项目
  • 3 个机器账户

这些免费额度对于大多数小型或中型团队来说已足够使用。

如何集成 GitHub Actions?

Bitwarden Secrets Manager 便于与 GitHub Actions 等 CI/CD 服务进行集成。

以下是一个简单的示例,展示了如何在 GitHub Actions 中获取并使用存储在 Bitwarden 中的机密。

首先,在 GitHub Actions 的工作流 YAML 文件中,添加获取机密的步骤:

- name: Get Secrets
  uses: bitwarden/sm-action@v2
  with:
    access_token: ${{ secrets.BW_ACCESS_TOKEN }}
    base_url: https://vault.bitwarden.com
    secrets: |
      fc3a93f4-2a16-445b-b0c4-aeaf0102f0ff > SECRET_NAME_1
      bdbb16bc-0b9b-472e-99fa-af4101309076 > SECRET_NAME_2

在上面的示例中,fc3a93f4-2a16-445b-b0c4-aeaf0102f0ffbdbb16bc-0b9b-472e-99fa-af4101309076 是存储在 Bitwarden Secrets Manager 中的机密 ID,而 SECRET_NAME_1SECRET_NAME_2 是引用机密的名称,用于在后续步骤中进行使用。

接着,在后续步骤中,使用这些机密值:

- name: Use Secret
  run: SQLCMD -S MYSQLSERVER -U "$SECRET_NAME_1" -P "$SECRET_NAME_2"

完整示例:

- name: Get Secrets
  uses: bitwarden/sm-action@v2
  with:
    access_token: ${{ secrets.BW_ACCESS_TOKEN }}
    secrets: |
      fc3a93f4-2a16-445b-b0c4-aeaf0102f0ff > GITHUB_GPG_PRIVATE_KEY
      bdbb16bc-0b9b-472e-99fa-af4101309076 > GITHUB_GPG_PRIVATE_KEY_PASSPHRASE

- name: Import GPG key
  uses: crazy-max/ghaction-import-gpg@v6
  with:
    gpg_private_key: ${{ env.GITHUB_GPG_PRIVATE_KEY }}
    passphrase: ${{ env.GITHUB_GPG_PRIVATE_KEY_PASSPHRASE }}
    git_user_signingkey: true
    git_commit_gpgsign: true

更多集成方式请参考 官方文档

Secrets Manager CLI 使用

为了便于在本地查询和管理机密,Bitwarden 提供了强大的 Secrets Manager CLI 工具。可以通过它来创建、删除、编辑和列出机密。

GitHub Releases 下载适合操作系统的可执行文件,运行以下命令以查看帮助信息:

bws --help

使用 Secrets Manager CLI 时,需先配置访问令牌(Access Token),然后运行如下命令列出机密:

# 设置环境变量
export BWS_ACCESS_TOKEN=xxxxxx
bws secret list

# 或者从命令行传入
bws secret list --access-token xxxxxx

Alfred Workflow 集成

为了进一步提高效率,写了一个小工具,帮助在 macOS 上快速查询并复制 Secrets。

Alfred Workflow 效果

以下是完整的 PHP 脚本示例:

<?php

$tokenName = !empty($argv[1]) ? trim($argv[1]) : '';
$accessToken = getenv('BWS_ACCESS_TOKEN');
$iconPngUrl = 'icon.png';

$json = `bws secret list -t '{$accessToken}'`;
if (!$json) {
    echo json_encode(['items' => [['title' => 'Error: Failed to fetch secrets', 'valid' => false]]]);
    exit;
}

$list = json_decode($json, true);

$items = [];

foreach ($list as $item) {
    if (!empty($tokenName) && stripos($item['key'], $tokenName) === false) {
        continue;
    }

    $items[] = [
        'arg' => $item['value'],
        'title' => $item['key'],
        'subtitle' => $item['note'],
        'icon' => ['path' => $iconPngUrl],
        'valid' => true,
    ];
}

if (empty($items)) {
    $items[] = [
        'title' => 'No secrets found',
        'valid' => false
    ];
}

echo json_encode(['items' => $items]);
exit;

Bitwarden Secrets Manager 为 DevOps 团队提供了一种更加安全、便捷的方式来管理和集成机密信息。

无论是与 GitHub Actions 集成,还是使用 CLI 工具进行本地管理,Bitwarden 都提供了简洁而强大的功能,帮助提升工作效率并确保敏感数据的安全。

MySQL 字符集与大小写敏感性解析

2025-02-25 14:24:31

在 MySQL 数据库中,UTF-8 及其变体是最常用的字符集。

不同的 UTF-8 编码可能对大小写敏感性产生影响,主要包括以下几种:

  • utf8:MySQL 早期的 UTF-8 实现,最多支持 3 字节,无法存储部分 Emoji 字符。
  • utf8mb4:MySQL 5.5+ 版本推荐使用的 UTF-8 编码,最多支持 4 字节,能够完整存储所有 Unicode 字符。

字符集与排序规则(Collation)

MySQL 字符集搭配不同的排序规则(Collation)可能会影响查询的大小写敏感性。

常见的排序规则包括:

  • utf8_general_ci / utf8mb4_general_ci:不区分大小写(Case Insensitive,ci 代表 Case Insensitive)。
  • utf8_bin / utf8mb4_bin:区分大小写(Binary,bin 代表按二进制存储,严格区分大小写)。
  • utf8_unicode_ci / utf8mb4_unicode_ci:更符合 Unicode 规范的排序方式,不区分大小写。

默认情况下,utf8_general_ciutf8mb4_general_ci 在搜索时是不区分大小写的。

MySQL 大小写搜索问题

当 MySQL 表的字符集设置为 utf8_general_ciutf8mb4_general_ci 时,使用 LIKE= 进行查询时,默认是不区分大小写的。

例如:

SELECT * FROM users WHERE username = 'admin';

如果数据库中存储了 AdminADMIN 等,查询会返回这些所有匹配项。

如果需要执行区分大小写的查询,则需要:

  1. 修改排序规则(Collation)
ALTER TABLE users MODIFY username VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

这样查询就会严格区分 adminAdmin

  1. 使用 BINARY 关键字
SELECT * FROM users WHERE BINARY username = 'admin';

这样 admin 只会匹配完全相同的字符串,而不会匹配 AdminADMIN 等。

在 ThinkPHP 框架中使用 whereRaw 进行原生查询

在 ThinkPHP 框架中,默认的 where 方法不支持直接使用 BINARY 进行查询,但可以通过 whereRaw 方法执行 MySQL 原生查询。

$result = Db::table('users')
    ->whereRaw("BINARY username = ?", ['admin'])
    ->find();

$result = Db::table('users')
    ->whereRaw("BINARY username LIKE ?", ['%admin%'])
    ->select();

这种方法可以避免默认的大小写不敏感查询,让 MySQL 进行更严格的匹配。

总结

  • MySQL 的 utf8_general_ciutf8mb4_general_ci 默认不区分大小写。
  • 需要区分大小写时,可以修改排序规则(Collation)或使用 BINARY 关键字。
  • 在 ThinkPHP 框架中,可以使用 whereRaw 方法执行 MySQL 原生查询,确保大小写敏感匹配。

这样,你就可以在 ThinkPHP 框架中更灵活地处理 MySQL 字符集大小写敏感的问题。

在命令行中输出带颜色的日志

2025-01-15 18:09:21

在命令行界面(CLI)中输出带颜色的日志不仅能提升可读性,还能帮助开发人员在调试时迅速区分不同类型的日志信息。

通过使用 ANSI 转义序列,我们可以很方便地控制输出文本的颜色、样式和其他显示效果,如加粗、下划线、反显等。

本文将详细介绍如何使用这些序列输出带颜色的日志。

什么是 ANSI 转义序列?

ANSI 转义序列是一种用于控制终端文本格式的字符序列。

它通常以 \033[\e[ 开头,后接不同的控制代码,最后以 m 结尾。

例如,\033[32m 表示设置文本颜色为绿色,\033[0m 用来重置样式。

利用 ANSI 转义序列,开发者可以灵活地在命令行中输出不同颜色和效果的文本。

常见的 ANSI 转义序列控制

  • \033[0m:关闭所有属性,恢复为默认设置
  • \033[1m:设置高亮度(加深显示)
  • \033[4m:设置下划线
  • \033[5m:设置闪烁
  • \033[7m:反显(替换背景色和前景色)
  • \033[8m:消隐(隐藏文本)
  • \033[30m\033[37m:设置前景色(字体颜色)
  • \033[40m\033[47m:设置背景色
  • \033[nA:光标上移 n 行
  • \033[nB:光标下移 n 行
  • \033[nC:光标右移 n 行
  • \033[nD:光标左移 n 行
  • \033[y;xH:设置光标位置为 y 行 x 列
  • \033[2J:清屏
  • \033[K:清除从光标到行尾的内容
  • \033[s:保存光标位置
  • \033[u:恢复光标位置
  • \033[?25l:隐藏光标
  • \033[?25h:显示光标

常见的颜色和效果

字体颜色(前景色)

  • 30: 黑色
  • 31: 红色
  • 32: 绿色
  • 33: 黄色
  • 34: 蓝色
  • 35: 紫色
  • 36: 深绿色
  • 37: 白色

背景颜色

  • 40: 黑色背景
  • 41: 红色背景
  • 42: 绿色背景
  • 43: 黄色背景
  • 44: 蓝色背景
  • 45: 紫色背景
  • 46: 深绿色背景
  • 47: 白色背景

显示效果

  • 0: 默认(无效果)
  • 1: 高亮(加深显示)
  • 2: 低亮(减弱显示)
  • 4: 下划线
  • 5: 闪烁
  • 7: 反显(替换前景色和背景色)
  • 8: 消隐(隐藏文本)

示例代码

  1. 简单的颜色输出

最简单的颜色控制是设置文本的前景色。例如,以下代码将输出绿色文本:

echo "\033[32m绿色\033[0m"

033[32m 设置文本为绿色,033[0m 用于重置所有属性,使后续输出恢复默认样式。

  1. 加粗和下划线

我们可以结合多种样式来增强文本的可读性。例如,下面的代码将输出一个带下划线的红色文本:

echo "\033[4;31m下划线红色\033[0m"

这里,4 表示下划线,31 表示红色。

  1. 发出声音提示

除了颜色和样式,ANSI 转义序列还可以控制终端的其他行为,比如发出声音。

这行命令会在终端发出一声铃声,同时输出一段普通文本:

echo "\007发出'咚~'一声\033[0m"

请注意,在某些终端环境下,铃声可能不会响起,尤其是在没有扬声器的设备上。

  1. 设置背景色和前景色

你还可以同时设置文本的前景色和背景色。例如,以下代码将输出一个白色背景和红色前景的文本:

echo "\033[47;31m白底红字\033[0m"

47 是背景色(白色),31 是前景色(红色)。

  1. 结合多个效果

通过组合多个效果,你可以创建更具视觉冲击力的输出。比如,以下代码将输出一个蓝色加粗下划线的文本:

echo "\033[1;4;34m蓝色加粗下划线\033[0m"

在这个示例中,1 表示加粗,4 表示下划线,34 表示蓝色。

  1. 光标控制和清屏

ANSI 转义序列还允许控制光标的位置和终端屏幕的清理。例如:

echo "\033[2J"  # 清屏
echo "\033[10;5H光标移动到第10行第5列\033[0m"
  1. 隐藏和显示光标

你还可以隐藏和显示光标:

echo "\033[?25l"  # 隐藏光标
echo "\033[?25h"  # 显示光标

实现效果

通过使用 ANSI 转义序列,我们可以轻松地为命令行中的输出添加颜色和样式。

这不仅能让调试日志变得更加易读,还能增强命令行工具的用户体验。

你可以根据需求结合不同的颜色、效果和光标控制,创建自定义的命令行输出,通过这些技术,命令行的输出变得更加生动和富有表现力,有助于开发人员快速识别关键信息。