init
This commit is contained in:
commit
e8833b172d
2 files changed
+1526
No files matched your search
@@ -0,0 +1,476 @@
|
||||
# aiagent.sh — 100% POSIX-sh 自然语言运维 Agent
|
||||
|
||||
> 一行英文句子 = 一条运维命令。不用背参数,不用记 flag。
|
||||
|
||||
`aiagent.sh` 是一个**纯 `/bin/sh` 实现**的轻量级"AI Agent"。它不需要 Python、不需要 node、不需要任何运行时——单文件、零依赖,却能把你输入的**自然英语句子**解析成真实的运维操作。
|
||||
|
||||
```sh
|
||||
$ ./aiagent.sh
|
||||
aiagent> please show disk usage
|
||||
[INFO] Disk usage:
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/sda1 100G 42G 58G 42% /
|
||||
|
||||
aiagent> what is the uptime
|
||||
[INFO] System uptime:
|
||||
14:32:11 up 12 days, 3:17, 2 users, load average: 0.12, 0.08, 0.01
|
||||
|
||||
aiagent> check port 8080
|
||||
[INFO] Checking port 8080 ...
|
||||
[OK] Port 8080 is IN USE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心特性
|
||||
|
||||
| 特性 | 说明 |
|
||||
|------|------|
|
||||
| 🗣️ **自然语言输入** | 接受完整英文句子,不需要任何特殊语法 |
|
||||
| 🧠 **意图识别** | 自动提取动词、名词、路径、端口、服务名 |
|
||||
| 🔄 **同义词归一** | `show/display/list` → 统一处理,`kill/stop/terminate` → 统一处理 |
|
||||
| 🎯 **名词推断动作** | 只说 `uptime` 也能理解成"show uptime" |
|
||||
| 🔒 **安全确认** | 所有破坏性操作(删除、杀进程、装包)强制 `y/N` 二次确认 |
|
||||
| 🛡️ **零 eval 注入** | 没有任何字符串拼接执行,包管理器直接调用 |
|
||||
| ⚙️ **自动适配环境** | 自动检测 `systemctl`/`service`、`ss`/`netstat`、`apt`/`dnf`/`yum`/`apk`/`pacman` |
|
||||
| 🧩 **可扩展** | 每个 `do_xxx()` 函数独立,新增操作只需加一个 case 分支和一个函数 |
|
||||
| 📦 **单文件分发** | 约 1050 行,直接 `cp` 到目标机就能跑 |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速上手
|
||||
|
||||
### 1. 获取脚本
|
||||
|
||||
```bash
|
||||
# 从git仓库获取
|
||||
git clone https://github.com/CancerXiaoAi/shell-ai.git
|
||||
git clone https://git.cancerai.top/cancerai/shell-ai.git
|
||||
```
|
||||
|
||||
### 2. 两种使用方式
|
||||
|
||||
```bash
|
||||
# 方式 A:交互式 REPL(推荐日常使用)
|
||||
./aiagent.sh
|
||||
|
||||
# 方式 B:一行命令模式(适合脚本/CI)
|
||||
./aiagent.sh "please check port 443"
|
||||
./aiagent.sh "what is the kernel version"
|
||||
./aiagent.sh "health check"
|
||||
```
|
||||
|
||||
### 3. 最简示例
|
||||
|
||||
```bash
|
||||
# 系统一句话
|
||||
./aiagent.sh uptime # 直接说名词就行
|
||||
./aiagent.sh disk
|
||||
./aiagent.sh health
|
||||
|
||||
# 完整句子也没问题
|
||||
./aiagent.sh "please help me show memory usage"
|
||||
./aiagent.sh "could you ping google.com for me"
|
||||
./aiagent.sh "i want to restart nginx"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📖 完整命令参考
|
||||
|
||||
### 💡 语法约定
|
||||
|
||||
脚本对输入的容忍度极高。以下写法**全部等价**:
|
||||
|
||||
```
|
||||
please help me check disk usage
|
||||
help me check disk
|
||||
check disk
|
||||
disk
|
||||
```
|
||||
|
||||
规则:
|
||||
- `please`、`help me`、`to`、`a`、`the`、`can you`、`would you` 等纯语法词**全部自动忽略**
|
||||
- 只带名词(如 `uptime`)会被自动推断为"show + 该名词"
|
||||
- 只带动词加短语(如 `check port 80`)直接路由
|
||||
|
||||
### 🖥️ 系统信息 — System Info
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `show disk usage` / `disk` | `df -h` | 磁盘使用情况 |
|
||||
| `check memory` / `memory` / `ram` | `/proc/meminfo` 或 `free -h` | 内存占用 |
|
||||
| `check cpu load` / `cpu` / `load` | `/proc/loadavg` | CPU 负载 |
|
||||
| `what is the uptime` / `uptime` | `uptime` | 系统运行时长 |
|
||||
| `show kernel version` / `version` | `/etc/os-release` + `uname` | OS 和内核版本 |
|
||||
| `show listening ports` | `ss -tulnp` 或 `netstat -tulnp` | 监听端口 |
|
||||
| `who is logged in` / `show users` | `who` | 当前登录用户 |
|
||||
| `health check` / `check` | 一键跑 uptime + CPU + 内存 + 磁盘 | 健康检查 |
|
||||
|
||||
### 📂 文件操作 — Files
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `list files in /var/log` | `ls -lah /var/log` | 列出目录 |
|
||||
| `show me content of /etc/hosts` | `ls /etc/hosts` | 查看文件 |
|
||||
| `find files named *.log in /tmp` | `find /tmp -type f -name "*.log"` | 查找文件 |
|
||||
| `find process nginx` | `ps aux | grep nginx` | 按名字找进程 |
|
||||
| `create directory /data` | `mkdir -p /data` | 创建目录 |
|
||||
| `create file /tmp/hello.txt` | `: > /tmp/hello.txt` | 创建空文件 |
|
||||
| `copy /etc/hosts /tmp/hosts.bak` | `cp -r/-f` | 自动判断文件/目录复制 |
|
||||
| `move /tmp/a.log /var/log/` | `mv -f` | 移动/重命名 |
|
||||
|
||||
### ⚠️ 破坏性操作 — Destructive(强制 y/N 确认)
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `please remove /tmp/cache` | `rm -rf`(确认后) | 递归删目录 |
|
||||
| `delete file /tmp/bad.log` | `rm -f`(确认后) | 删除文件 |
|
||||
| `clean old log files in /var/log` | `find -delete`(确认后) | 清理日志 |
|
||||
| `kill process nginx` | `kill` + PID 列表(确认后) | 按名字杀进程 |
|
||||
| `kill the process on port 8080` | 先 lsof/ss 找 PID(确认后) | 按端口杀进程 |
|
||||
| `stop nginx` | `systemctl stop`(确认后) | 停服务 |
|
||||
|
||||
### 🔌 服务管理 — Services
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `check status of sshd` | `systemctl status` | 查看服务状态 |
|
||||
| `start docker service` | `systemctl start` | 启动服务 |
|
||||
| `restart nginx` | `systemctl restart` | 重启服务 |
|
||||
| `nginx` | 自动识别服务名 → 查状态 | 裸服务名默认查状态 |
|
||||
|
||||
### 🌐 网络 — Network
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `check port 443` / `port 443` | `ss`/`netstat`/`nc` | 检查端口监听状态 |
|
||||
| `ping google.com` | `ping -c 3 -W 2` | 连通性测试(3 包) |
|
||||
| `show listening ports` | `ss -tulnp` | 所有监听端口 |
|
||||
|
||||
### 📦 包管理 — Packages
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `please install package htop` | 自动检测 `apt-get`/`dnf`/`yum`/`apk`/`pacman` 并调用 | 安装系统包(确认后) |
|
||||
|
||||
### 📜 日志 — Logs
|
||||
|
||||
| 输入示例 | 实际调用 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `tail /var/log/syslog` | `tail -30` | 直接路径 |
|
||||
| `tail nginx log` | 自动匹配 `/var/log/nginx/access.log` | 按服务名猜路径 |
|
||||
| `follow docker log` | glob `/var/log/*docker*` | 模糊匹配 |
|
||||
|
||||
### 🎛️ 其他
|
||||
|
||||
| 输入 | 说明 |
|
||||
|------|------|
|
||||
| `help` | 打印帮助手册 |
|
||||
| `quit` / `exit` / `bye` | 退出 REPL |
|
||||
|
||||
---
|
||||
|
||||
## 🧠 自然语言解析原理
|
||||
|
||||
整个解析管线分为 **5 层**,每一层都只使用 POSIX sh 原语实现:
|
||||
|
||||
```
|
||||
用户输入:please help me check port 8080
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────┐
|
||||
│ 第 1 层:strip_fillers() │
|
||||
│ 丢弃纯语法词:please, help, me │
|
||||
└─────────────────────────────────┘
|
||||
│ 得到:check port 8080
|
||||
▼
|
||||
┌─────────────────────────────────┐
|
||||
│ 第 2 层:跳过引导词 │
|
||||
│ 跳过开头的 help/what/can 等客气词│
|
||||
└─────────────────────────────────┘
|
||||
│ 得到:check port 8080
|
||||
▼
|
||||
┌─────────────────────────────────┐
|
||||
│ 第 3 层:canonical_verb() │
|
||||
│ 动词→同义词归一 │
|
||||
│ 名词→推断动作(health→check) │
|
||||
└─────────────────────────────────┘
|
||||
│ verb=check, phrase="port 8080"
|
||||
▼
|
||||
┌─────────────────────────────────┐
|
||||
│ 第 4 层:dispatch() 一级匹配 │
|
||||
│ case "$phrase" in *port*) │
|
||||
│ do_check_port; _matched=1 ;; │
|
||||
└─────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────┐
|
||||
│ 第 5 层:do_check_port() │
|
||||
│ 从短语中提取 "8080" │
|
||||
│ 依次尝试 ss → netstat → nc │
|
||||
│ 输出 [OK]/[WARN] 状态 │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 动词同义词映射(canonical_verb)
|
||||
|
||||
```
|
||||
show ← show, display, list, print, tell, what, reveal, dump
|
||||
check ← check, monitor, verify, inspect, diagnose
|
||||
find ← find, locate, search, lookup, track
|
||||
remove← remove, delete, erase, rm, wipe, cleanup, clean
|
||||
kill ← kill, stop, terminate, shutdown, halt
|
||||
start ← start, launch, run, begin, enable
|
||||
...
|
||||
```
|
||||
|
||||
### 名词 → 推断动作
|
||||
|
||||
```
|
||||
uptime, disk, memory, cpu, version, port, process ... → 自动当作 show
|
||||
health, status, connection, reachability → 自动当作 check
|
||||
```
|
||||
|
||||
### 三级 fallback 匹配机制
|
||||
|
||||
每个规范动词的路由都有三级兜底:
|
||||
|
||||
1. **一级关键词匹配**:`*disk*` → do_show_disk,`*port*` → do_check_port
|
||||
2. **二级兜底**:短语是纯数字 → 当作端口号;短语含已知服务名 → do_service_status
|
||||
3. **三级兜底**:`check` 空短语 → do_health_check;其他 → 提示用户重述
|
||||
|
||||
---
|
||||
|
||||
## 🔒 安全设计
|
||||
|
||||
### 强制二次确认
|
||||
|
||||
以下操作**必须**输入 `y` 或 `yes` 才会继续,其他任何输入都视为取消:
|
||||
|
||||
- 删除目录/文件(`remove`, `delete`)
|
||||
- 杀进程(`kill`)
|
||||
- 停服务(`stop service`)
|
||||
- 安装系统包(`install`)
|
||||
|
||||
```
|
||||
[CONFIRM] Recursively remove directory '/tmp/cache' ? (y/N):
|
||||
```
|
||||
|
||||
### 零 eval 注入
|
||||
|
||||
整个脚本**没有任何 `eval` 调用**。包管理器的调用采用直接分支方式:
|
||||
|
||||
```sh
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get install -y -- "$_pkg" # 直接调用,参数安全引用
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
dnf install -y -- "$_pkg"
|
||||
...
|
||||
```
|
||||
|
||||
### 路径安全
|
||||
|
||||
`rm -rf`、`mv`、`cp` 等危险操作都使用了 `--` 分隔符,防止路径以 `-` 开头被解释为选项。
|
||||
|
||||
### 信号处理
|
||||
|
||||
REPL 模式下按 Ctrl+C 会优雅退出,不会留下终端异常状态:
|
||||
|
||||
```sh
|
||||
trap 'echo; printf "Bye.\n"; exit 130' INT TERM
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 架构总览
|
||||
|
||||
```
|
||||
aiagent.sh (~1050 lines, 单文件)
|
||||
├── 辅助函数层
|
||||
│ ├── info() / warn() / error() / success() # 带颜色的日志输出
|
||||
│ └── confirm() # y/N 安全确认
|
||||
│
|
||||
├── 解析层(第 1–3 层)
|
||||
│ ├── strip_fillers() # 丢弃纯语法词
|
||||
│ ├── canonical_verb() # 同义词归一 + 名词推断
|
||||
│ ├── _extract_path() # 从短语中提取路径
|
||||
│ ├── _extract_svcname() # 从短语中提取服务名
|
||||
│ └── _SERVICES_RE # 已知服务名正则
|
||||
│
|
||||
├── 路由层(第 4 层)
|
||||
│ └── dispatch() # 大 case 分支,三级 fallback
|
||||
│
|
||||
├── 执行层(第 5 层)
|
||||
│ ├── do_show_disk / _memory / _cpu / _uptime / _version / ...
|
||||
│ ├── do_check_port / do_ping_host / do_service_status / do_health_check
|
||||
│ ├── do_find_process / do_find_file
|
||||
│ ├── do_remove_dir / _file / _log
|
||||
│ ├── do_kill_process / do_kill_by_port
|
||||
│ ├── do_service_start / _restart / _stop
|
||||
│ ├── do_create_dir / _file
|
||||
│ ├── do_copy_path / do_move_path
|
||||
│ ├── do_install_pkg
|
||||
│ └── do_tail_log
|
||||
│
|
||||
├── REPL 层
|
||||
│ ├── run_one() # 单次命令处理管线
|
||||
│ └── repl() # 交互式循环
|
||||
│
|
||||
└── 入口
|
||||
└── main() # 分交互式/一行模式
|
||||
```
|
||||
|
||||
### 依赖关系图
|
||||
|
||||
```
|
||||
main() ─→ repl() 或 run_one()
|
||||
│
|
||||
▼
|
||||
dispatch()
|
||||
│
|
||||
┌─────────┼─────────────┬──────────┬────────────┐
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
show() check() find() remove() install()
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
do_show_* do_check_* do_find_* do_remove_* do_install_pkg
|
||||
│
|
||||
▼
|
||||
confirm() ←── 所有 destructive 函数必经
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ 运行要求
|
||||
|
||||
### 最低要求
|
||||
|
||||
| 项目 | 要求 |
|
||||
|------|------|
|
||||
| Shell 解释器 | `/bin/sh`(POSIX sh,任何实现均可:dash / busybox / bash --posix) |
|
||||
| 操作系统 | Linux(主要目标);macOS 可读但部分功能受限(无 systemctl/ss) |
|
||||
| 权限 | 普通用户即可运行,执行破坏性/管理类命令时需要相应权限 |
|
||||
|
||||
### 可选依赖(根据操作自动探测)
|
||||
|
||||
| 操作 | 依赖(择一) |
|
||||
|------|-------------|
|
||||
| 磁盘/内存/CPU | `df`, `/proc/meminfo` 或 `free`, `/proc/loadavg` |
|
||||
| 服务管理 | `systemctl` 或 `service` |
|
||||
| 端口检查 | `ss` / `netstat` / `nc` |
|
||||
| 进程查找 | `ps`, `pgrep`(可选) |
|
||||
| 进程/端口杀 | `pgrep`, `lsof`, `fuser`(择一) |
|
||||
| 网络 | `ping` |
|
||||
| 文件查找 | `find` |
|
||||
| 包安装 | `apt-get` / `dnf` / `yum` / `apk` / `pacman`(择一) |
|
||||
|
||||
### 跨包管理器支持
|
||||
|
||||
| 发行版 | 自动使用 |
|
||||
|--------|---------|
|
||||
| Debian / Ubuntu | `apt-get` |
|
||||
| RHEL 8+ / Fedora / CentOS 8+ | `dnf` |
|
||||
| RHEL 7 / CentOS 7 | `yum` |
|
||||
| Alpine | `apk` |
|
||||
| Arch / Manjaro | `pacman` |
|
||||
|
||||
---
|
||||
|
||||
## ⚡ 性能
|
||||
|
||||
解析管线全部使用 POSIX sh 内建实现(`case` / `for` / `if` / `read` / `printf`),**不 fork 任何外部进程**——除了 `grep -qE` 和 `awk` 在少数 fallback 分支里会被调用。整个"strip → canonical → dispatch → route"管线的纯解析开销**可以忽略不计**,实际耗时主要来自底层命令本身(如 `df -h`、`ps aux`、`systemctl` 等)。
|
||||
|
||||
---
|
||||
|
||||
## 🧪 快速验证
|
||||
|
||||
在 Docker 容器里跑一下(无需在本机安装任何东西):
|
||||
|
||||
```bash
|
||||
# Debian
|
||||
docker run --rm -it -v $(pwd)/aiagent.sh:/aiagent.sh debian:latest \
|
||||
sh -c 'chmod +x /aiagent.sh && /aiagent.sh "health check"'
|
||||
|
||||
# Alpine
|
||||
docker run --rm -it -v $(pwd)/aiagent.sh:/aiagent.sh alpine:latest \
|
||||
sh -c 'chmod +x /aiagent.sh && /aiagent.sh "check port 22"'
|
||||
|
||||
# CentOS / Rocky / AlmaLinux
|
||||
docker run --rm -it -v $(pwd)/aiagent.sh:/aiagent.sh rocky:9 \
|
||||
sh -c 'chmod +x /aiagent.sh && /aiagent.sh "restart sshd"'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 扩展指南
|
||||
|
||||
想新增一个操作(比如"备份数据库")?三个步骤:
|
||||
|
||||
**步骤 1**:加一个规范动词映射(如果是新动词)
|
||||
|
||||
```sh
|
||||
canonical_verb() {
|
||||
...
|
||||
backup|dump) echo "backup" ;;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**步骤 2**:在 `dispatch()` 的 case 分支里加路由
|
||||
|
||||
```sh
|
||||
dispatch() {
|
||||
...
|
||||
backup)
|
||||
do_backup_db "$phrase" ;;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**步骤 3**:实现 `do_backup_db()` 函数
|
||||
|
||||
```sh
|
||||
do_backup_db() {
|
||||
_db=""
|
||||
for _tok in $1; do
|
||||
case "$_tok" in mysql|postgres|redis|mongodb) _db="$_tok" ;; esac
|
||||
done
|
||||
[ -z "$_db" ] && { error "No DB type. Example: 'backup mysql'"; return 1; }
|
||||
confirm "Backup $_db ?" || return 1
|
||||
# 实际备份逻辑
|
||||
case "$_db" in
|
||||
mysql) mysqldump ... ;;
|
||||
postgres) pg_dump ... ;;
|
||||
...
|
||||
esac
|
||||
}
|
||||
```
|
||||
|
||||
完成。现在 `./aiagent.sh "please backup mysql database"` 就能工作了。
|
||||
|
||||
---
|
||||
|
||||
## 🐛 已知限制
|
||||
|
||||
| 限制 | 说明 |
|
||||
|------|------|
|
||||
| 只能识别**英文** | 整个关键词库是英语 hardcode 的,不支持中文 |
|
||||
| 正则只支持 POSIX ERE | 不支持 PCRE(但对运维场景已足够) |
|
||||
| 交互式 REPL 不支持命令历史 | POSIX sh 的 `read` 没有 readline;可以通过 `rlwrap ./aiagent.sh` 获得历史 |
|
||||
| 端口号从短语提取用的是 `[0-9]*` | 如果句子里有多个数字,会取最后一个(对"check port 80 on server 192.168.1.1"这种会取 1) |
|
||||
| macOS 功能受限 | 没有 `systemctl`/`ss`/`/proc/*`,部分操作会降级或报依赖缺失 |
|
||||
| 包管理器自动检测 | 只是检测命令是否存在,不检查是否真的可用(例如在 chroot 里) |
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT License. 复制、修改、商用均自由,唯一要求保留版权声明。
|
||||
|
||||
---
|
||||
|
||||
## 🙏 致谢
|
||||
|
||||
- POSIX 标准委员会:没有你们就没有可移植的 shell
|
||||
- 所有写出漂亮运维命令的前辈:你们的 `df -h`、`ps aux`、`ss -tulnp` 是这个项目的基石
|
||||
Reference in new issue
Block a user