日志散在多台服务器怎么查?用 Promtail + Loki + Grafana 搭一套集中检索平台

前言

应用出错时,我最怕的不是看到一条报错,而是明知道异常发生了,却不知道该去哪台机器、哪个目录找它。登录服务器、翻 server.log、对照时间,再切到另一套服务继续查,日志越分散,定位问题花的时间就越多。Promtail、Loki 和 Grafana 这套 PLG 组合适合解决的,正是把日志采集、存储和查询分成三个明确的环节:Promtail 盯住文件并发送日志,Loki 按标签组织日志流,Grafana 则提供查询与展示入口。它不等于把所有日志都建成全文索引,查问题时要先选对标签,再用 LogQL 缩小范围。比如半夜收到一个接口报错,我希望先按应用名找到对应日志流,再对照异常时间和请求内容,而不是在几台机器之间反复切换、凭印象猜测。

这篇我会沿着两条路线实际梳理:先看 CentOS 7 下分别部署二进制程序的方式,再看使用 Docker Compose 一起启动三个组件的方法。后一条路线还会从 test.log 开始写入测试消息,接着验证 JSON 日志、Nginx 和认证日志的查询,最后用 cpolar 把 Grafana 的 3000 页面提供给异地浏览器。两条路线的端口、版本和存储目录并不相同,不能互相照搬;尤其是权限、匿名访问和数据持久化,我更愿意在上线前逐项确认,而不是只看到容器运行就算完成。

一、先认清三个组件的分工

如果只是偶尔登录一台服务器看一份日志,直接用命令行通常足够;当应用、容器和主机越来越多,分散的文件才开始影响排障。PLG 的请求方向是 Promtail 读取日志 → 推送给 Loki → Grafana 查询 Loki ,不是 Grafana 直接扫描各台机器的文件。Promtail 可以按文件路径采集并添加 job、host 等标签;Loki 主要索引标签、保存日志内容;Grafana 使用 LogQL 按标签、关键词或解析后的字段筛选。需要接入指标或链路追踪时,再分别连接相应的数据源,不能把这份日志部署直接等同于完整三件套可观测平台。

例如 {job="app"} |= "error" 用于筛选包含错误关键词的应用日志,{job="nginx"} |~ "404|500" 用于匹配状态码文本,rate({job="api"}[5m]) 则可统计指定时间窗口的日志速率。对比需要全文索引的方案,这种标签优先的检索方式适合明确知道服务名、来源或环境的排障;实际资源开销仍取决于日志量、标签基数和部署规模。

二、CentOS 7:先分开安装三个组件

这条路线需要 root 或 sudo 权限,并且机器能够下载软件包。文中的防火墙示例同时给出了关闭服务和按端口开放两种思路,实际长期运行时应优先确认需要开放的端口,而不是把关闭防火墙当成监控系统的前提。尤其需要区分 Loki 的二进制端口 8094、Promtail 的 9080 与 Grafana 的 3000;开头提及的 3100 是后面 Docker 方案使用的 Loki 端口。

shell 复制代码
systemctl stop firewalld
systemctl disable firewalld
# 或使用 iptables/firewalld 开放端口

准备 wget、tar、curl、vim 和网络工具,再创建可选的 Loki 专用账号:

shell 复制代码
yum update -y
yum install -y wget tar curl vim net-tools
shell 复制代码
useradd -r -s /sbin/nologin loki

先运行 Loki:接收日志并保存到磁盘

安装说明文字提到 v3.0.0,但实际下载命令指向的是 v1.5.0 。应当以真正下载并运行的二进制为准,不要把后面的 Docker 2.9.10 配置当作同一版本使用。执行以下命令前,还应确认 /app/loki 目录已经存在;它在命令中被直接 cd 进入,并没有先创建。

shell 复制代码
cd /app/loki
curl -O -L "https://github.com/grafana/loki/releases/download/v1.5.0/loki-linux-amd64.zip" 

解压命令使用 unzip,而前面的基础安装清单没有包含它,若提示命令不存在,需要先在系统环境中准备该工具。

shell 复制代码
unzip loki-linux-amd64.zip

日志块和索引分别放在 /data/loki/chunks、/data/loki/index,这部分是二进制方案的本地存储位置:

shell 复制代码
mkdir  /data/loki
mkdir  /data/loki/{chunks,index}

编辑 config.yaml:

shell 复制代码
vi config.yaml
shell 复制代码
auth_enabled: false
server:
  http_listen_port: 8094
ingester:
  lifecycler:
    address: 192.168.42.140 #日志服务器ip,即本机地址
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_sleep: 0s
  chunk_idle_period: 5m
  chunk_retain_period: 30s
schema_config:
  configs:
  - from: 2024-04-01
    store: boltdb
    object_store: filesystem
    schema: v11
    index:
      prefix: index_
      period: 168h   #每张表的时间范围7天
storage_config:
  boltdb:
    directory: /data/loki/index   #索引文件存储地址
  filesystem:
    directory: /data/loki/chunks  #块存储地址
limits_config:
  enforce_metric_name: false
  reject_old_samples: true
  reject_old_samples_max_age: 168h
chunk_store_config:
  max_look_back_period: 168h

table_manager:
  retention_deletes_enabled: true
  retention_period: 168h   #表的保留期7天

这份配置关闭了 Loki 内置认证,在 192.168.42.140 所在服务器使用单副本 ring,将 HTTP 入口设为 8094,并设置了七天相关的保留参数。由于配置包含旧版存储 schema,应该配合实际下载的二进制核对适用性,不要简单替换成较新版本后继续照抄。auth_enabled: false 也意味着不能直接把 Loki 接口当作已完成授权保护的公网服务。

随后创建启动和停止脚本,前者后台执行二进制并记录 pid,后者根据 pid 停止进程。原有 kill -9 属于强制结束命令,运行前要核对 pid 文件确实属于对应 Loki 进程。

shell 复制代码
vi start.sh
shell 复制代码
#!/bin/bash
nohup ./loki-linux-amd64 -config.file=./config.yaml >./server.log 2>&1 &
echo "$!" > pid
shell 复制代码
vi shutdown.sh
shell 复制代码
#!/bin/bash
kill -9 `cat pid`
echo "关闭成功!"

脚本准备好以后启动并查看输出日志;如果没有收到 Promtail 的数据,先确认 Loki 自身能稳定启动,再继续查采集端。

shell 复制代码
sh start.sh
shell 复制代码
tail -200f server.log

再安装 Grafana:给日志提供查询界面

这里又给出了一组关闭 firewalld 和 SELinux 的命令,属于对主机安全机制的明显放宽。它们按技术示例保留,但不能据此理解为 Grafana 必须在关闭这些防护后才能工作。

shell 复制代码
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

安装方式按照系统包形式分别列出,真正使用 CentOS 的演示选的是 RPM 命令。不要在同一台机器上把下面不同平台的安装方式依次执行。

Ubuntu / Debian:

shell 复制代码
sudo apt-get install -y adduser libfontconfig1 musl
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_12.1.0_amd64.deb
sudo dpkg -i grafana-enterprise_12.1.0_amd64.deb

Standalone Linux Binaries:

shell 复制代码
wget https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0.linux-amd64.tar.gz
tar -zxvf grafana-enterprise-12.1.0.linux-amd64.tar.gz

Red Hat / CentOS / RHEL / Fedora:

shell 复制代码
sudo yum install -y https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm

OpenSUSE / SUSE:

shell 复制代码
wget https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm
sudo rpm -Uvh grafana-enterprise-12.1.0-1.x86_64.rpm

本次 CentOS 使用的命令再次列出:

shell 复制代码
sudo yum install -y https://dl.grafana.com/enterprise/release/grafana-enterprise-12.1.0-1.x86_64.rpm

安装 Grafana Enterprise 12.1.0 后,启动服务并设置开机自启,再查看版本号:

shell 复制代码
systemctl restart grafana-server
systemctl enable grafana-server
shell 复制代码
grafana-cli -version

浏览器访问服务器的 3000 端口。代码框里的 ip:3000 是访问地址示意,不是要在 shell 中执行的命令。

shell 复制代码
ip:3000

首次登录使用示例账号 admin/admin,进入后按页面提示修改密码;这也是后面考虑远程开放前必须完成的基础动作。

最后安装 Promtail:把目标日志送到 Loki

采集端放在 /app/promtail,实际下载也是 v1.5.0,与前面的二进制 Loki 路线相对应。路径需要先存在,再下载、解压并创建配置文件。

shell 复制代码
cd /app/promtail
curl -O -L "https://github.com/grafana/loki/releases/download/v1.5.0/promtail-linux-amd64.zip"
shell 复制代码
unzip promtail-linux-amd64.zip
shell 复制代码
vi promtail.yaml
shell 复制代码
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: ./positions.yaml

clients:
  - url: http://192.168.42.140:8094/loki/api/v1/push #日志服务器loki地址和端口

scrape_configs:
#ucenter1
 - job_name: zcbackend-172.29.21.22-1
   static_configs:
   - targets:
       - 192.168.42.140
   - labels:
      job: zcbachend-172.29.21.22-1
      host: 192.168.42.140
      __path__: /jiuqi/zichan/zichanyitihuazhenghexiangmu-8084/backend/server.log  #本机日志路径

这份配置把日志发送到 http://192.168.42.140:8094/loki/api/v1/push,读取的具体文件是 /jiuqi/zichan/zichanyitihuazhenghexiangmu-8084/backend/server.log,并设置 job、host 等标签。这个路径和 IP 代表演示环境,迁移到自己的机器时必须与真实日志路径对应。配置里的 static_configs 列表和标签缩进也需要按实际 YAML 结构核对;如果 Promtail 不启动,优先检查配置解析报错。positions.yaml 用于记录读取位置,它的路径在此处是相对路径。

同样创建启动脚本和关闭脚本,启动后查看日志。这里展示了创建 shutdown.sh 的命令及截图,但没有给出它的具体内容,不能默认它已经和 Loki 的停止脚本完全一致。

shell 复制代码
vi start.sh
shell 复制代码
#!/bin/bash
nohup ./promtail-linux-amd64 -config.file=./promtail.yaml >./server.log 2>&1 &
echo "$!" > pid
shell 复制代码
vi shutdown.sh
shell 复制代码
sh start.sh
shell 复制代码
tail -200f server.log

到这里,二进制部署的三层职责就明确了:Promtail 读文件,Loki 在 8094 接收,Grafana 在 3000 展示。接下来是另一套完整 Docker 路线,不应在现有服务还占用相同端口时直接叠加运行。

三、Docker Compose:把 PLG 放到同一网络

如果更希望用统一的配置管理组件,可以选择 Docker 方案。先检查 Docker:

shell 复制代码
docker --version

创建项目目录的示例里,实际创建的是 /docker/do,但权限命令操作的却是 /do。这是两个不同路径,不应直接理解为创建目录后已经正确授权;而且递归 777 会让目录对所有用户开放,长期部署需要更明确地控制权限。

shell 复制代码
mkdir -p /docker/do
chmod -R 777 /do

准备 Loki 与 Promtail 的配置文件

下面的命令一次写入两个配置。此时 Loki 使用 3100,Promtail 通过 Docker 网络里的 http://loki:3100/loki/api/v1/push 发送日志;采集范围包括 /var/log/*.log 与 /var/log/test.log。这些值专属于 Docker 路线,不能和上面的 8094 配置混用。

shell 复制代码
mkdir -p /docker/do/loki
# 创建配置文件
cat > /docker/do/loki/config.yml <<EOF
 auth_enabled: false

 server:
   http_listen_port: 3100

 common:
   path_prefix: /tmp/loki
   storage:
     filesystem:
       directory: /tmp/loki/chunks
   replication_factor: 1
   ring:
     kvstore:
       store: inmemory

 schema_config:
   configs:
     - from: 2020-10-24
       store: boltdb-shipper
       object_store: filesystem
       schema: v11
       index:
         prefix: index_
         period: 24h
 EOF

# 创建目录
mkdir -p /docker/do/promtail

# 创建配置文件
# 创建配置文件
cat > /docker/do/promtail/config.yml <<EOF
 server:
   http_listen_port: 9080
   grpc_listen_port: 0

 positions:
   filename: /tmp/positions.yaml

 clients:
   - url: http://loki:3100/loki/api/v1/push

 scrape_configs:
   - job_name: system
     static_configs:
       - targets:
           - localhost
         labels:
           job: varlogs
           __path__: /var/log/*.log
   - job_name: test
     static_configs:
       - targets:
           - localhost
         labels:
           job: test
           __path__: /var/log/test.log
 EOF

这段 shell 使用 here-document 写文件,实际粘贴执行时需要特别检查 EOF 结束符是否独占一行、前面没有多余缩进,否则可能导致文件写入没有如预期结束。还有一个更容易忽略的地方:Loki 数据在配置中位于 /tmp/loki,但后面的 Compose 没有为它挂载宿主机持久化目录。不能仅凭容器运行,就认定日志和索引在容器重建后还会保存。

编辑 docker-compose.yml:

shell 复制代码
vi docker-compose.yml
shell 复制代码
version: "3"

networks:
  loki:

services:
  loki:
    image: grafana/loki:2.9.10
    ports:
      - "3100:3100"
    volumes:
      - ./loki/config.yml:/etc/loki/config.yml          # 👈 挂载配置
    command: -config.file=/etc/loki/config.yml          # 👈 路径匹配
    networks:
      - loki

  promtail:
    image: grafana/promtail:2.9.10
    volumes:
      - /var/log:/var/log
      - ./promtail/config.yml:/etc/promtail/config.yml  # 👈 挂载配置
    command: -config.file=/etc/promtail/config.yml      # 👈 路径匹配
    networks:
      - loki
    user: "root"                                        # 👈 关键!避免权限问题

  grafana:
    environment:
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
    entrypoint:
      - sh
      - -euc
      - |
        mkdir -p /etc/grafana/provisioning/datasources
        cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
        apiVersion: 1
        datasources:
        - name: Loki
          type: loki
          access: proxy
          orgId: 1
          url: http://loki:3100
          basicAuth: false
          isDefault: true
          version: 1
          editable: false
        EOF
        /run.sh
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    networks:
      - loki

Docker 镜像这里明确是 grafana/loki:2.9.10 和 grafana/promtail:2.9.10,与前面下载的 v1.5.0 不同;Grafana 则使用 grafana/grafana:latest。Compose 里还通过初始化文件让 Grafana 自动添加名为 Loki 的数据源,指向 Docker 网络中的 http://loki:3100。

但这份 Grafana 环境变量同时设置 GF_AUTH_ANONYMOUS_ENABLED=true 和 GF_AUTH_ANONYMOUS_ORG_ROLE=Admin:匿名访问者可能获得管理员权限。它可以作为需要重点检查的演示配置,却不适合原样配合公网隧道长期开放。Promtail 使用 user: "root" 读取主机 /var/log,也应结合实际日志权限评估。

启动后先看容器是否能够运行:

shell 复制代码
docker-compose up -d

四、从测试日志验证,不只看页面是否打开

进入 Grafana,查看 Loki 数据源、连接测试和 Explore。Compose 中已经包含自动添加数据源的配置,界面中的"添加数据源"步骤可用于核对连接,不必把两个动作理解成必须重复操作。

先向 /var/log/test.log 写一行测试消息。Docker 的 Promtail 已把主机 /var/log 挂进容器,因此这份日志有明确的采集路径。

shell 复制代码
echo "Test log entry at $(date)" >> /var/log/test.log

然后调用 Loki 查询接口:

shell 复制代码
curl -g 'http://localhost:3100/loki/api/v1/query?query={job="test"}&limit=5'

如果响应的 values 数组出现刚写入的日志,就比"Loki 页面可以访问"更能说明 文件 → Promtail → Loki 已经打通。再进入 Grafana Explore,选择 Loki 数据源并运行下面的 LogQL:

shell 复制代码
{job="test"}

此时完整链路才变成 日志文件 → Promtail → Loki → Grafana。如果 Loki API 有数据而 Explore 没显示,就该检查 Grafana 的数据源及查询;如果 API 也没有数据,先查 Promtail 采集路径、发送端地址和 positions 文件。

五、加入 JSON、Nginx 和认证日志

基础链路跑通以后,再模拟更接近真实应用的日志。先创建 /var/log/app.json,里面分别放入登录成功、数据库超时、限流三条 JSON 日志;ts、level、status、path 等字段都保留在日志内容中。

shell 复制代码
# 模拟一个 Web 服务日志
cat > /var/log/app.json <<'EOF'
{"level":"info","ts":"2026-06-04T12:00:00Z","msg":"User login","user_id":1001,"ip":"192.168.1.10","method":"POST","path":"/login","status":200}
{"level":"error","ts":"2026-06-04T12:01:05Z","msg":"DB timeout","user_id":1002,"ip":"192.168.1.11","method":"GET","path":"/profile","status":500,"error":"context deadline exceeded"}
{"level":"warn","ts":"2026-06-04T12:02:30Z","msg":"Rate limit hit","user_id":1003,"ip":"192.168.1.12","method":"POST","path":"/api/v1/send","status":429}
EOF

更新 Promtail 的配置,让它除了测试日志,还收集 app.json:

shell 复制代码
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: test
    static_configs:
      - targets:
          - localhost
        labels:
          job: test
          __path__: /var/log/test.log

  - job_name: app-json
    pipeline_stages:
      - json:
          expressions:
            level: level
            msg: msg

    static_configs:
      - targets:
          - localhost
        labels:
          job: app
          __path__: /var/log/app.json

这里的 pipeline_stages 只从 JSON 中提取 level 和 msg 。代码没有 labels 阶段,更没有把 status 配成 Loki 索引标签,因此不能把它写成"level、status 已经都成为标签"。后面的 LogQL | json 是查询时解析日志内容,和写入时建立标签也不是同一个动作。

修改配置后重启 Promtail:

shell 复制代码
docker-compose restart promtail

在 Explore 中先按错误级别筛选,再按 HTTP 状态码筛选:

shell 复制代码
{job="app"} | json | level = "error"
shell 复制代码
{job="app"} | json | status >= 500

还可以用原示例统计请求量:

shell 复制代码
sum by (path) (
  count_over_time({job="app"}[5m])
)

这里需要注意,sum by (path) 想按 path 分组,得先确认这个字段是否被解析成可供聚合的标签;配置示例本身没有完成该步骤。因此不能根据这一条查询就断言已实现正确的逐路径统计。

再模拟 Nginx 访问日志与认证日志:

shell 复制代码
# 模拟 nginx 日志
echo '192.168.1.10 - - [04/Jun/2026:12:10:00 +0000] "GET /api/v1/data HTTP/1.1" 200 1024' >> /var/log/nginx-access.log

# 模拟 auth 服务日志
echo "$(date -Iseconds) [AUTH] User 1001 logged in from 192.168.1.10" >> /var/log/auth.log

把它们和原来的测试、应用 JSON 日志一起纳入 Promtail 配置:

shell 复制代码
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: test
    static_configs:
      - targets: [localhost]
        labels:
          job: test
          __path__: /var/log/test.log

  - job_name: app-json
    pipeline_stages:
      - json:
          expressions:
            level: level
            msg: msg
    static_configs:                     # ← 必须在这里!
      - targets: [localhost]
        labels:
          job: app
          __path__: /var/log/app.json

  - job_name: nginx
    static_configs:
      - targets: [localhost]
        labels:
          job: nginx
          __path__: /var/log/nginx-access.log

  - job_name: auth
    static_configs:
      - targets: [localhost]
        labels:
          job: auth
          __path__: /var/log/auth.log

新的标签包括 job: test、job: app、job: nginx、job: auth。重启采集端后,可以在 Grafana 中切换不同 job,根据时间关联认证日志和 Nginx 访问记录。这样做只证明不同来源能进入同一查询入口,不等于应用之间已经自动完成链路追踪。

六、异地查看日志:只为 Grafana 配公网入口

本地查询确认以后,若需要在另一处网络查看面板,可以用 cpolar 映射 Grafana 的 3000。这条隧道解决的是 浏览器到 Grafana 的网络入口;日志依然由 Promtail 采集并送到 Loki,不会因为建立公网地址而改由 cpolar 采集。尤其在开放之前,应先收紧上面 Docker 配置中的匿名管理员权限,并确认登录凭据和访问范围。

先安装 cpolar 并查看服务状态:

shell 复制代码
sudo curl https://get.cpolar.sh | sh
shell 复制代码
sudo systemctl status cpolar

通过服务器 IP 加 9200 进入 cpolar 管理界面。示例文字显示的是 192.168.42.101:9200,所附 Markdown 链接实际指向 localhost:9200/,使用时按访问设备所在网络选择能到达的地址。

进入 隧道管理 → 创建隧道 ,填写隧道名称 grafana、HTTP、本地地址 3000、随机域名、地区 China Top。这里的 3000 是 Grafana,不是 Loki 的 3100,更不是二进制路线的 8094。

进入在线隧道列表复制生成的公网地址,用其他电脑或移动设备测试:

随机地址能打开 Grafana 后,如果需要相对固定的远程入口,再到预留页面选择 保留二级子域名 ,地区 china top,本例名称为 grafana3。名称具有唯一性,以自己账号实际预留成功的结果为准。

回到隧道列表编辑 grafana,把域名类型切换为二级子域名,Sub Domain 填入刚保留的名称,地区选 China Top,然后更新。

再使用固定地址从外部访问:

公网页面能打开只说明网络入口有效。最后还应登录 Grafana、选择 Loki 数据源、按 job 查到真实日志,才算跨网络查看的使用链路完整。固定域名不意味着主机永远在线,也不能代替 Grafana 的身份验证和权限控制。

总结

把 PLG 当成三个独立职责,排障就更有次序:Promtail 负责找到文件并推送,Loki 负责保存和按标签组织日志流,Grafana 负责查询与展示。对我来说,真正值得确认的是一条测试日志是否先出现在 Loki API,再出现在 Grafana Explore;随后才是 JSON 字段过滤、多日志源查询和远程访问。

二进制和 Compose 都能表达这套结构,但配置不能混搭。v1.5.0 与 2.9.10、8094 与 3100、本地数据目录与未持久化的 /tmp/loki,以及匿名管理员配置,都需要按所选路线逐项核对。cpolar 让远程浏览器能打开 Grafana,却不替日志系统存储、检索或加固权限;把本地链路和公网访问分开处理,后面扩展告警或多台服务器时才有稳定的基础。

相关推荐
CHENKONG_CK1 小时前
恶劣工况下 RFID 赋能喷涂产线自动化分拣与作业
运维·网络·人工智能·自动化·汽车·rfid·rfid
北京中科新远科技1 小时前
AI集群交换网络容量怎么算:端口、收敛比与Leaf-Spine验收
服务器·网络·人工智能
wdfk_prog1 小时前
Wi-Fi Direct 教程 04:Interface 协议子系统初始化——WPA/EAPOL、WPS、DPP/NAN、GAS 与 P2P callback
android·运维·服务器·ubuntu·p2p·wps·wifi-direct
云飞云共享云桌面1 小时前
有个10人的SolidWorks设计团队,服务器什么配置合适,如何落地
运维·服务器·3d·自动化·电脑·制造
逆向编程1 小时前
VMware仅主机(Host‑Only,VMnet1)物理机‑虚拟机文件共享完整实操
运维
ai小陈1 小时前
GPU算力平台远程训练监控:TensorBoard与SSH隧道配置实战
运维·人工智能·深度学习·ai·ssh·gpu算力
adminwolf1 小时前
抖音个人号私信自动化回复浏览器扩展,非破解协议,合规的RPA手段
运维·自动化·rpa
爱吃香菜的初学者1 小时前
十二.Linux——管道
linux·运维·服务器
BullSmall3 小时前
规则+大模型混合评测:高效精准双保障
运维·自动化