feat(ssh-setup): 添加 SSH 自动化配置工具文档与脚本
- 新增 AGENTS.md,详细描述博客项目编码规范和智能助手操作指南 - 添加 ssh-setup 脚本用于交互式自动配置 SSH 连接密钥与别名 - 实现密钥生成、备份配置、自动部署公钥与连接测试功能 - 提供彩色日志输出和详细错误处理提升用户体验 - 包含安装、使用方法和故障排除说明文档 - 支持自动创建 shell 别名和配置文件更新 - 确保配置安全性和兼容多种 shell 环境
This commit is contained in:
218
AGENTS.md
Normal file
218
AGENTS.md
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
# AGENTS.md - MyBlog 编码指南
|
||||||
|
|
||||||
|
本文档为在此 VuePress 博客项目中工作的智能编码助手提供指南。
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
这是一个基于以下技术构建的个人博客:
|
||||||
|
- **框架**: VuePress v2 (静态站点生成器)
|
||||||
|
- **主题**: VuePress Theme Hope
|
||||||
|
- **语言**: TypeScript + Vue 3
|
||||||
|
- **构建工具**: Vite
|
||||||
|
- **包管理器**: npm
|
||||||
|
|
||||||
|
## 构建/代码检查/测试命令
|
||||||
|
|
||||||
|
### 开发
|
||||||
|
```bash
|
||||||
|
# 启动开发服务器
|
||||||
|
npm run docs:dev
|
||||||
|
|
||||||
|
# 清除缓存后启动开发服务器
|
||||||
|
npm run docs:clean-dev
|
||||||
|
|
||||||
|
# 构建生产版本
|
||||||
|
npm run docs:build
|
||||||
|
|
||||||
|
# 更新 VuePress 包
|
||||||
|
npm run docs:update-package
|
||||||
|
|
||||||
|
# 更新 browserslist 数据库
|
||||||
|
npm run update:browsers
|
||||||
|
```
|
||||||
|
|
||||||
|
### 测试与质量
|
||||||
|
本项目没有配置显式的测试命令。由于是 VuePress 博客:
|
||||||
|
- package.json 中没有配置单元测试
|
||||||
|
- 通过 `npm run docs:build` 进行构建验证
|
||||||
|
- 通过 `npm run docs:dev` 进行开发服务器验证
|
||||||
|
|
||||||
|
### 类型检查
|
||||||
|
```bash
|
||||||
|
# TypeScript 类型检查(如果需要)
|
||||||
|
npx tsc --noEmit
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码风格指南
|
||||||
|
|
||||||
|
### 文件结构
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── .vuepress/ # VuePress 配置
|
||||||
|
│ ├── config.ts # 站点配置
|
||||||
|
│ ├── theme.ts # 主题配置
|
||||||
|
│ ├── navbar.ts # 导航栏配置
|
||||||
|
│ ├── sidebar.ts # 侧边栏配置
|
||||||
|
│ ├── styles/ # 自定义样式
|
||||||
|
│ └── components/ # Vue 组件
|
||||||
|
├── programming/ # 编程相关文章
|
||||||
|
├── apps/ # 应用部署指南
|
||||||
|
├── tools/ # 工具分享
|
||||||
|
├── work/ # 工作日志
|
||||||
|
└── README.md # 首页
|
||||||
|
```
|
||||||
|
|
||||||
|
### TypeScript 配置
|
||||||
|
- **模块系统**: ES 模块 (package.json 中的 `"type": "module"`)
|
||||||
|
- **目标版本**: ES2022
|
||||||
|
- **模块解析**: NodeNext
|
||||||
|
- **包含文件**: `src/.vuepress/**/*.ts` 和 `src/.vuepress/**/*.vue`
|
||||||
|
|
||||||
|
### 导入语句
|
||||||
|
- 使用 ES 模块导入: `import { defineUserConfig } from "vuepress";`
|
||||||
|
- 需要时显式导入类型
|
||||||
|
- 分组导入:框架导入在前,本地导入在后
|
||||||
|
- 使用 config.ts 中定义的路径别名(如果可用)
|
||||||
|
|
||||||
|
### TypeScript 使用
|
||||||
|
- 所有配置文件都使用 TypeScript
|
||||||
|
- 为函数参数和返回值定义显式类型
|
||||||
|
- 对复杂数据结构使用接口
|
||||||
|
- 结合 TypeScript 使用 Vue 3 的 Composition API
|
||||||
|
|
||||||
|
### Vue 组件
|
||||||
|
- 使用 Vue 3 Composition API 和 `<script setup>` 语法
|
||||||
|
- 使用 TypeScript 接口定义 props
|
||||||
|
- 使用 `ref()` 和 `reactive()` 处理响应式状态
|
||||||
|
- 遵循现有组件的 VuePress 组件模式
|
||||||
|
|
||||||
|
### Markdown 文件
|
||||||
|
- 使用 YAML frontmatter 存储元数据:
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: 文章标题
|
||||||
|
icon: simple-icons:iconname
|
||||||
|
date: YYYY-MM-DD
|
||||||
|
category:
|
||||||
|
- 分类名称
|
||||||
|
tag:
|
||||||
|
- 标签1
|
||||||
|
- 标签2
|
||||||
|
---
|
||||||
|
```
|
||||||
|
- 包含 `<!-- more -->` 标签作为文章摘要
|
||||||
|
- 使用中文内容 (zh-CN)
|
||||||
|
- 遵循现有文章结构,包含清晰的章节
|
||||||
|
|
||||||
|
### 命名约定
|
||||||
|
- **文件**: Markdown 文件使用 kebab-case,Vue 组件使用 PascalCase
|
||||||
|
- **变量**: camelCase
|
||||||
|
- **常量**: UPPER_SNAKE_CASE
|
||||||
|
- **函数**: camelCase,描述性名称
|
||||||
|
- **类型/接口**: PascalCase
|
||||||
|
- **目录**: kebab-case
|
||||||
|
|
||||||
|
### 错误处理
|
||||||
|
- 对异步操作使用 try-catch
|
||||||
|
- 验证配置对象
|
||||||
|
- 提供有意义的错误信息
|
||||||
|
- 适当记录错误(开发时使用 console.error)
|
||||||
|
|
||||||
|
### 格式化
|
||||||
|
- **缩进**: 2 个空格(不使用制表符)
|
||||||
|
- **行长度**: 目标 80-100 个字符
|
||||||
|
- **分号**: 使用分号
|
||||||
|
- **引号**: 字符串使用单引号,模板字面量使用反引号
|
||||||
|
- **尾随逗号**: 在多行对象和数组中使用
|
||||||
|
|
||||||
|
### CSS/样式
|
||||||
|
- 使用 SCSS 进行自定义样式(已安装 sass-embedded)
|
||||||
|
- 自定义类遵循 BEM 命名约定
|
||||||
|
- 使用 CSS 自定义属性(变量)进行主题化
|
||||||
|
- 利用 VuePress Theme Hope 的内置样式
|
||||||
|
|
||||||
|
### Git 实践
|
||||||
|
- **提交消息**: 使用约定式提交格式
|
||||||
|
- **分支命名**: feature/描述, fix/描述, docs/描述
|
||||||
|
- **.gitignore**: 已配置为忽略 node_modules、dist、缓存文件
|
||||||
|
|
||||||
|
### 配置文件
|
||||||
|
- **config.ts**: 主要 VuePress 配置
|
||||||
|
- **theme.ts**: 主题自定义
|
||||||
|
- **navbar.ts**: 导航结构
|
||||||
|
- **sidebar.ts**: 侧边栏组织
|
||||||
|
- 遵循这些文件中的现有模式
|
||||||
|
|
||||||
|
### 性能考虑
|
||||||
|
- 优化 `src/.vuepress/public/` 中的图片
|
||||||
|
- 对图片使用懒加载 (`imgLazyload: true`)
|
||||||
|
- 通过仅导入所需组件来最小化打包大小
|
||||||
|
- 使用 VuePress 内置优化
|
||||||
|
|
||||||
|
### 可访问性
|
||||||
|
- 使用语义化 HTML 元素
|
||||||
|
- 为图片提供 alt 文本
|
||||||
|
- 确保正确的标题层级
|
||||||
|
- 保持键盘导航支持
|
||||||
|
|
||||||
|
### 国际化
|
||||||
|
- 主要语言: 中文 (zh-CN)
|
||||||
|
- 在 `config.ts` 中配置: `lang: "zh-CN"`
|
||||||
|
- 所有面向用户的内容使用中文
|
||||||
|
- 保持一致的术语
|
||||||
|
|
||||||
|
### 部署
|
||||||
|
- 构建输出: `src/.vuepress/dist/`
|
||||||
|
- 兼容静态托管
|
||||||
|
- 如果需要,在 `config.ts` 中配置基础路径
|
||||||
|
- 确保所有相对路径正常工作
|
||||||
|
|
||||||
|
## 智能助手特定指令
|
||||||
|
|
||||||
|
1. **修改前**: 始终运行 `npm run docs:dev` 验证更改是否有效
|
||||||
|
2. **修改后**: 运行 `npm run docs:build` 确保生产构建成功
|
||||||
|
3. **添加文章时**: 遵循现有的 frontmatter 和结构模式
|
||||||
|
4. **修改配置时**: 检查现有配置文件中的模式
|
||||||
|
5. **创建组件时**: 放置在 `src/.vuepress/components/` 并遵循 Vue 3 模式
|
||||||
|
6. **更新依赖时**: 使用 `npm run docs:update-package` 更新 VuePress 包
|
||||||
|
|
||||||
|
## 常见任务
|
||||||
|
|
||||||
|
### 添加新文章
|
||||||
|
1. 在适当目录中创建 Markdown 文件
|
||||||
|
2. 添加包含标题、日期、分类、标签的 YAML frontmatter
|
||||||
|
3. 编写包含清晰章节标题的内容
|
||||||
|
4. 包含 `<!-- more -->` 标签作为摘要
|
||||||
|
5. 如果需要,添加到侧边栏配置
|
||||||
|
|
||||||
|
### 修改主题
|
||||||
|
1. 编辑 `src/.vuepress/theme.ts`
|
||||||
|
2. 查阅 VuePress Theme Hope 文档
|
||||||
|
3. 在开发模式下测试更改
|
||||||
|
4. 验证生产构建
|
||||||
|
|
||||||
|
### 添加自定义组件
|
||||||
|
1. 在 `src/.vuepress/components/` 中创建 Vue 组件
|
||||||
|
2. 如果需要,在配置中注册
|
||||||
|
3. 在 Markdown 或其他组件中导入并使用
|
||||||
|
4. 在开发中测试
|
||||||
|
|
||||||
|
### 更新导航
|
||||||
|
1. 编辑 `src/.vuepress/navbar.ts`
|
||||||
|
2. 遵循现有结构
|
||||||
|
3. 测试导航功能
|
||||||
|
4. 验证移动端响应性
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
- **构建失败**: 检查 TypeScript 错误、缺失的依赖
|
||||||
|
- **开发服务器无法启动**: 尝试 `npm run docs:clean-dev`
|
||||||
|
- **图片无法加载**: 验证 `public/` 目录中的路径
|
||||||
|
- **样式未应用**: 检查 SCSS 编译、导入顺序
|
||||||
|
|
||||||
|
### 调试
|
||||||
|
1. 检查浏览器控制台中的错误
|
||||||
|
2. 验证终端中的 VuePress 日志
|
||||||
|
3. 在开发者工具中检查生成的 HTML
|
||||||
|
4. 如果需要,使用干净缓存测试
|
||||||
540
src/programming/linux/Linux_Mint/SSH自动化配置工具.md
Normal file
540
src/programming/linux/Linux_Mint/SSH自动化配置工具.md
Normal file
@@ -0,0 +1,540 @@
|
|||||||
|
---
|
||||||
|
title: SSH-SETUP 自动化配置工具
|
||||||
|
icon: simple-icons:linuxmint
|
||||||
|
date: 2026-01-14
|
||||||
|
category:
|
||||||
|
- Linux
|
||||||
|
tag:
|
||||||
|
- Linux Mint
|
||||||
|
- SSH
|
||||||
|
- 自动化脚本
|
||||||
|
---
|
||||||
|
|
||||||
|
# SSH-SETUP 自动化配置工具
|
||||||
|
|
||||||
|
一个交互式 SSH 配置脚本,用于自动化设置 SSH 密钥认证、服务器连接别名和免密登录。
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
## 一 工具概述
|
||||||
|
|
||||||
|
`ssh-setup` 是一个 Bash 脚本,旨在简化 SSH 服务器的配置过程。通过交互式引导,用户可以快速完成以下任务:
|
||||||
|
|
||||||
|
- 🔑 生成或选择 SSH 密钥
|
||||||
|
- 🌐 配置服务器连接信息
|
||||||
|
- 🔄 自动部署公钥到远程服务器
|
||||||
|
- 📝 更新 SSH 配置文件
|
||||||
|
- 🚀 创建便捷的 shell 别名
|
||||||
|
|
||||||
|
### 1.1 核心功能
|
||||||
|
|
||||||
|
- ✅ **密钥管理**: 支持生成新密钥或使用现有密钥
|
||||||
|
- ✅ **交互式配置**: 引导用户输入服务器信息
|
||||||
|
- ✅ **自动部署**: 一键部署公钥到远程服务器
|
||||||
|
- ✅ **配置备份**: 自动备份现有 SSH 配置
|
||||||
|
- ✅ **连接测试**: 配置完成后自动测试连接
|
||||||
|
- ✅ **别名创建**: 为每个服务器创建快捷别名
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二 安装与配置
|
||||||
|
|
||||||
|
### 2.1 脚本位置
|
||||||
|
- **路径**: `~/bin/ssh-setup`
|
||||||
|
- **权限**: 可执行 (`-rwxrwxr-x`)
|
||||||
|
- **大小**: 359 行代码
|
||||||
|
|
||||||
|
### 2.2 环境配置
|
||||||
|
- **PATH 设置**: `~/bin` 已添加到 PATH
|
||||||
|
- **Shell 别名**: 已添加 `ssh-setup` 别名到 `~/.bashrc`
|
||||||
|
- **配置文件更新**:
|
||||||
|
- `~/.bashrc` - 已优化 PATH 配置
|
||||||
|
- `~/.profile` - 已优化 PATH 配置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三 使用方法
|
||||||
|
|
||||||
|
### 3.1 启动方式
|
||||||
|
|
||||||
|
#### 方法一:使用别名(推荐)
|
||||||
|
```bash
|
||||||
|
ssh-setup
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方法二:使用完整路径
|
||||||
|
```bash
|
||||||
|
~/bin/ssh-setup
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方法三:在新终端中
|
||||||
|
1. 打开新终端窗口
|
||||||
|
2. 直接运行: `ssh-setup`
|
||||||
|
|
||||||
|
### 3.2 配置流程
|
||||||
|
|
||||||
|
运行 `ssh-setup` 后,按照提示输入:
|
||||||
|
1. **服务器别名** - 如: `server1`
|
||||||
|
2. **IP 地址** - 如: `10.6.220.216`
|
||||||
|
3. **端口** - 默认: `22`,或输入如: `10022`
|
||||||
|
4. **用户名** - 默认: 当前用户,或输入如: `sunri`
|
||||||
|
5. **服务器密码** - 仅首次需要
|
||||||
|
|
||||||
|
### 3.3 配置完成后
|
||||||
|
- **连接方式**: `ssh server1`
|
||||||
|
- **快捷别名**: `ssh-server1` (需要重新加载 shell)
|
||||||
|
- **配置文件**: `~/.ssh/config` 自动更新
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四 技术特性
|
||||||
|
|
||||||
|
### 4.1 安全功能
|
||||||
|
- ✅ SSH 密钥认证(不存储密码)
|
||||||
|
- ✅ 配置自动备份
|
||||||
|
- ✅ 输入验证和错误处理
|
||||||
|
- ✅ 失败重试机制
|
||||||
|
|
||||||
|
### 4.2 自动化功能
|
||||||
|
- ✅ 自动部署公钥到服务器
|
||||||
|
- ✅ 自动更新 SSH config
|
||||||
|
- ✅ 自动创建 shell 别名
|
||||||
|
- ✅ 自动测试连接
|
||||||
|
|
||||||
|
### 4.3 用户体验
|
||||||
|
- ✅ 彩色输出和进度提示
|
||||||
|
- ✅ 详细的错误信息
|
||||||
|
- ✅ 交互式输入引导
|
||||||
|
- ✅ 配置总结报告
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五 立即使用
|
||||||
|
|
||||||
|
### 5.1 对于当前会话
|
||||||
|
```bash
|
||||||
|
# 1. 重新加载配置
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
# 2. 开始配置
|
||||||
|
ssh-setup
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 对于新终端
|
||||||
|
1. 打开新终端窗口
|
||||||
|
2. 直接运行: `ssh-setup`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六 验证配置
|
||||||
|
|
||||||
|
运行验证脚本检查配置:
|
||||||
|
```bash
|
||||||
|
~/verify-ssh-setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七 故障排除
|
||||||
|
|
||||||
|
### 7.1 如果 `ssh-setup` 命令未找到
|
||||||
|
```bash
|
||||||
|
# 方案1: 使用完整路径
|
||||||
|
~/bin/ssh-setup
|
||||||
|
|
||||||
|
# 方案2: 手动设置 PATH
|
||||||
|
export PATH="$HOME/bin:$PATH"
|
||||||
|
ssh-setup
|
||||||
|
|
||||||
|
# 方案3: 重新加载配置
|
||||||
|
source ~/.bashrc
|
||||||
|
ssh-setup
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 如果脚本权限问题
|
||||||
|
```bash
|
||||||
|
chmod +x ~/bin/ssh-setup
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八 功能实现确认
|
||||||
|
|
||||||
|
脚本已完全按照要求实现:
|
||||||
|
- ✅ 使用同一密钥
|
||||||
|
- ✅ 自动备份配置
|
||||||
|
- ✅ 服务器失败重试1次
|
||||||
|
- ✅ 密码错误直接提示用户
|
||||||
|
- ✅ 不支持批量导入
|
||||||
|
|
||||||
|
现在可以开始配置您的 SSH 连接了!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九 完整脚本代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ssh-setup - 自动化 SSH 配置脚本
|
||||||
|
# 版本: 1.0
|
||||||
|
# 功能: 交互式配置 SSH 密钥认证和连接别名
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查依赖
|
||||||
|
check_dependencies() {
|
||||||
|
log_info "检查系统依赖..."
|
||||||
|
|
||||||
|
local missing_deps=()
|
||||||
|
|
||||||
|
for cmd in ssh ssh-copy-id ssh-keygen; do
|
||||||
|
if ! command -v "$cmd" &> /dev/null; then
|
||||||
|
missing_deps+=("$cmd")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${#missing_deps[@]} -gt 0 ]; then
|
||||||
|
log_error "缺少必要的依赖: ${missing_deps[*]}"
|
||||||
|
log_info "请安装: sudo apt install openssh-client"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "所有依赖检查通过"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 初始化环境
|
||||||
|
init_environment() {
|
||||||
|
log_info "初始化环境..."
|
||||||
|
|
||||||
|
# 确保 ~/.ssh 目录存在
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
chmod 700 ~/.ssh
|
||||||
|
|
||||||
|
# 设置默认密钥路径
|
||||||
|
DEFAULT_KEY="${HOME}/.ssh/id_ed25519"
|
||||||
|
|
||||||
|
log_success "环境初始化完成"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 备份 SSH config
|
||||||
|
backup_ssh_config() {
|
||||||
|
local config_file="${HOME}/.ssh/config"
|
||||||
|
|
||||||
|
if [ -f "$config_file" ]; then
|
||||||
|
local backup_file="${config_file}.backup.$(date +%Y%m%d_%H%M%S)"
|
||||||
|
cp "$config_file" "$backup_file"
|
||||||
|
log_info "已备份 SSH config 到: $backup_file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 收集服务器信息
|
||||||
|
collect_server_info() {
|
||||||
|
log_info "请输入服务器配置信息"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
|
||||||
|
# 服务器别名
|
||||||
|
while true; do
|
||||||
|
read -p "服务器别名 (如: server1): " SERVER_ALIAS
|
||||||
|
SERVER_ALIAS=$(echo "$SERVER_ALIAS" | tr -d '[:space:]')
|
||||||
|
|
||||||
|
if [ -z "$SERVER_ALIAS" ]; then
|
||||||
|
log_error "别名不能为空"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查别名是否已存在
|
||||||
|
if [ -f "${HOME}/.ssh/config" ]; then
|
||||||
|
if grep -q "^Host[[:space:]]*${SERVER_ALIAS}[[:space:]]*$" "${HOME}/.ssh/config"; then
|
||||||
|
log_warning "别名 '$SERVER_ALIAS' 已存在"
|
||||||
|
read -p "是否覆盖? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
# IP 地址
|
||||||
|
while true; do
|
||||||
|
read -p "服务器 IP 地址: " SERVER_IP
|
||||||
|
SERVER_IP=$(echo "$SERVER_IP" | tr -d '[:space:]')
|
||||||
|
|
||||||
|
if [[ "$SERVER_IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
log_error "请输入有效的 IP 地址 (如: 10.6.220.216)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 端口
|
||||||
|
read -p "SSH 端口 [默认: 22]: " SERVER_PORT
|
||||||
|
SERVER_PORT=${SERVER_PORT:-22}
|
||||||
|
|
||||||
|
if ! [[ "$SERVER_PORT" =~ ^[0-9]+$ ]] || [ "$SERVER_PORT" -lt 1 ] || [ "$SERVER_PORT" -gt 65535 ]; then
|
||||||
|
log_error "端口号无效,使用默认值 22"
|
||||||
|
SERVER_PORT=22
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 用户名
|
||||||
|
read -p "用户名 [默认: $(whoami)]: " SERVER_USER
|
||||||
|
SERVER_USER=${SERVER_USER:-$(whoami)}
|
||||||
|
|
||||||
|
log_success "服务器信息收集完成"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo "别名: $SERVER_ALIAS"
|
||||||
|
echo "IP: $SERVER_IP"
|
||||||
|
echo "端口: $SERVER_PORT"
|
||||||
|
echo "用户: $SERVER_USER"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
|
||||||
|
read -p "确认以上信息? (Y/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
log_info "重新输入信息..."
|
||||||
|
collect_server_info
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 选择 SSH 密钥
|
||||||
|
select_ssh_key() {
|
||||||
|
log_info "选择 SSH 密钥..."
|
||||||
|
|
||||||
|
# 检查默认密钥是否存在
|
||||||
|
if [ -f "$DEFAULT_KEY" ] && [ -f "${DEFAULT_KEY}.pub" ]; then
|
||||||
|
log_info "发现现有密钥: $DEFAULT_KEY"
|
||||||
|
read -p "使用现有密钥? (Y/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
create_new_key
|
||||||
|
else
|
||||||
|
SSH_KEY="$DEFAULT_KEY"
|
||||||
|
log_success "使用现有密钥: $SSH_KEY"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_warning "未找到现有密钥"
|
||||||
|
create_new_key
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建新密钥
|
||||||
|
create_new_key() {
|
||||||
|
log_info "创建新的 SSH 密钥..."
|
||||||
|
|
||||||
|
read -p "密钥类型 [默认: ed25519]: " KEY_TYPE
|
||||||
|
KEY_TYPE=${KEY_TYPE:-ed25519}
|
||||||
|
|
||||||
|
read -p "密钥注释 [默认: $(whoami)@$(hostname)]: " KEY_COMMENT
|
||||||
|
KEY_COMMENT=${KEY_COMMENT:-"$(whoami)@$(hostname)"}
|
||||||
|
|
||||||
|
SSH_KEY="${HOME}/.ssh/id_${KEY_TYPE}"
|
||||||
|
|
||||||
|
if [ -f "$SSH_KEY" ]; then
|
||||||
|
log_warning "密钥文件已存在: $SSH_KEY"
|
||||||
|
read -p "是否覆盖? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
log_info "请选择其他密钥名称"
|
||||||
|
create_new_key
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "正在生成密钥..."
|
||||||
|
ssh-keygen -t "$KEY_TYPE" -C "$KEY_COMMENT" -f "$SSH_KEY" -N ""
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
log_success "密钥创建成功: $SSH_KEY"
|
||||||
|
else
|
||||||
|
log_error "密钥创建失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 部署公钥到服务器
|
||||||
|
deploy_public_key() {
|
||||||
|
log_info "部署公钥到服务器..."
|
||||||
|
|
||||||
|
local max_retries=1
|
||||||
|
local retry_count=0
|
||||||
|
|
||||||
|
while [ $retry_count -le $max_retries ]; do
|
||||||
|
echo "正在连接 ${SERVER_USER}@${SERVER_IP}:${SERVER_PORT}..."
|
||||||
|
|
||||||
|
# 使用 ssh-copy-id 部署公钥
|
||||||
|
if ssh-copy-id -p "$SERVER_PORT" -i "$SSH_KEY" "${SERVER_USER}@${SERVER_IP}"; then
|
||||||
|
log_success "公钥部署成功"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
retry_count=$((retry_count + 1))
|
||||||
|
|
||||||
|
if [ $retry_count -le $max_retries ]; then
|
||||||
|
log_warning "部署失败,正在重试 (${retry_count}/${max_retries})..."
|
||||||
|
sleep 2
|
||||||
|
else
|
||||||
|
log_error "公钥部署失败,请检查:"
|
||||||
|
log_error "1. 服务器是否可达"
|
||||||
|
log_error "2. 用户名和密码是否正确"
|
||||||
|
log_error "3. 服务器 SSH 服务是否运行"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 更新 SSH config
|
||||||
|
update_ssh_config() {
|
||||||
|
log_info "更新 SSH 配置文件..."
|
||||||
|
|
||||||
|
local config_file="${HOME}/.ssh/config"
|
||||||
|
|
||||||
|
# 创建或追加配置
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "# 自动配置: $SERVER_ALIAS - $(date)"
|
||||||
|
echo "Host $SERVER_ALIAS"
|
||||||
|
echo " HostName $SERVER_IP"
|
||||||
|
echo " Port $SERVER_PORT"
|
||||||
|
echo " User $SERVER_USER"
|
||||||
|
echo " IdentityFile $SSH_KEY"
|
||||||
|
echo " ServerAliveInterval 60"
|
||||||
|
echo " ServerAliveCountMax 3"
|
||||||
|
echo " ConnectTimeout 10"
|
||||||
|
echo ""
|
||||||
|
} >> "$config_file"
|
||||||
|
|
||||||
|
# 设置正确的权限
|
||||||
|
chmod 600 "$config_file"
|
||||||
|
|
||||||
|
log_success "SSH config 更新完成"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 测试连接
|
||||||
|
test_connection() {
|
||||||
|
log_info "测试 SSH 连接..."
|
||||||
|
|
||||||
|
if ssh -o ConnectTimeout=5 -o BatchMode=yes "$SERVER_ALIAS" "echo 'SSH 密钥认证成功'" 2>/dev/null; then
|
||||||
|
log_success "连接测试成功"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_warning "连接测试失败,但配置已保存"
|
||||||
|
log_info "您可能需要:"
|
||||||
|
log_info "1. 检查服务器防火墙设置"
|
||||||
|
log_info "2. 确认服务器 SSH 配置允许密钥认证"
|
||||||
|
log_info "3. 稍后手动测试: ssh $SERVER_ALIAS"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建 shell 别名
|
||||||
|
create_shell_alias() {
|
||||||
|
log_info "创建 shell 别名..."
|
||||||
|
|
||||||
|
local shell_rc
|
||||||
|
if [ -f "${HOME}/.zshrc" ]; then
|
||||||
|
shell_rc="${HOME}/.zshrc"
|
||||||
|
else
|
||||||
|
shell_rc="${HOME}/.bashrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local alias_name="ssh-${SERVER_ALIAS}"
|
||||||
|
local alias_cmd="alias ${alias_name}='ssh ${SERVER_ALIAS}'"
|
||||||
|
|
||||||
|
# 检查别名是否已存在
|
||||||
|
if ! grep -q "^${alias_cmd}$" "$shell_rc" 2>/dev/null; then
|
||||||
|
echo "$alias_cmd" >> "$shell_rc"
|
||||||
|
log_success "别名已添加到 $shell_rc"
|
||||||
|
log_info "运行 'source $shell_rc' 或重新打开终端后可使用: $alias_name"
|
||||||
|
else
|
||||||
|
log_info "别名已存在: $alias_name"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示使用说明
|
||||||
|
show_usage() {
|
||||||
|
echo "使用方法:"
|
||||||
|
echo " 直接连接: ssh $SERVER_ALIAS"
|
||||||
|
echo " 使用别名: ssh-$SERVER_ALIAS (需要重新加载 shell 配置)"
|
||||||
|
echo ""
|
||||||
|
echo "配置位置:"
|
||||||
|
echo " SSH config: ~/.ssh/config"
|
||||||
|
echo " 密钥文件: $SSH_KEY"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
echo "========================================"
|
||||||
|
echo " SSH 自动化配置工具 v1.0"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
# 检查依赖
|
||||||
|
check_dependencies
|
||||||
|
|
||||||
|
# 初始化环境
|
||||||
|
init_environment
|
||||||
|
|
||||||
|
# 备份现有配置
|
||||||
|
backup_ssh_config
|
||||||
|
|
||||||
|
# 收集服务器信息
|
||||||
|
collect_server_info
|
||||||
|
|
||||||
|
# 选择密钥
|
||||||
|
select_ssh_key
|
||||||
|
|
||||||
|
# 部署公钥
|
||||||
|
if ! deploy_public_key; then
|
||||||
|
log_warning "公钥部署失败,跳过后续步骤"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 更新配置
|
||||||
|
update_ssh_config
|
||||||
|
|
||||||
|
# 测试连接
|
||||||
|
test_connection
|
||||||
|
|
||||||
|
# 创建别名
|
||||||
|
create_shell_alias
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
log_success "配置完成!"
|
||||||
|
show_usage
|
||||||
|
echo "========================================"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 运行主函数
|
||||||
|
main "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user