mcporter 使用教程一、概述1. 简介A. 是什么mcporter 是一个用于调用 MCP（Model Context Protocol）服务器的 TypeScript 运行时和 CLI 工具。它提供了命令行界面来管理、测试和调用 MCP 服务器，让用户能够方便地使用各种 MCP 工具。B. 为什么学MCP 是连接 LLM 与外部服务的标准协议，掌握 mcporter 可以快速测试 MCP 服务器无需编写代码即可调用 MCP 工具，提高开发和调试效率支持多种配置来源，灵活管理 MCP 服务器C. 学完能做什么安装和配置 mcporter列出和查看已配置的 MCP 服务器使用命令行调用 MCP 工具排查配置问题二、环境准备1. 系统要求Node.js 14+ 和 npmLinux、macOS 或 Windows 操作系统网络连接（用于安装和访问远程 MCP 服务器）2. 安装步骤全局安装npm install -g mcporter如果遇到权限问题，使用 sudo：sudo npm install -g mcporter3. 验证安装mcporter --version输出示例：0.7.3列出已配置的服务器：mcporter list三、核心概念1. 基本术语MCP 服务器：提供一组工具的远程或本地服务工具（Tool）：MCP 服务器提供的具体功能接口选择器（Selector）：用于定位特定工具的语法，格式为 server.toolSSE：Server-Sent Events，mcporter 支持的通信协议之一2. 配置目录mcporter 从以下位置加载配置：平台配置路径Linux/macOS~/.mcporter/mcporter.jsonWindows%USERPROFILE%.mcporter\mcporter.json此外，mcporter 还会自动从编辑器（如 Cursor、Claude）的设置中导入服务器配置。3. 工作原理graph LR A[命令行] -->|mcporter call| B[解析器] B -->|查找服务器| C[配置文件] C -->|获取工具| D[MCP 服务器] D -->|返回结果| E[命令输出]四、快速上手1. Hello World 示例列出所有已配置的 MCP 服务器：mcporter list输出示例：mcporter 0.7.3 — Listing 7 server(s) (per-server timeout: 30s) - nagios-mcp (16 tools, 0.1s) - kali (12 tools, 0.2s) - web-search-prime (1 tool, 0.3s) [source: ~/.claude/settings.json] - web-reader (1 tool, 0.3s) [source: ~/.claude/settings.json] - zread (3 tools, 0.4s) [source: ~/.claude/settings.json] - zai-mcp-server (8 tools, 0.7s) [source: ~/.claude/settings.json] - wenyan-mcp (2 tools, 0.9s) [source: ~/.claude/settings.json] ✔ Listed 7 servers (7 healthy).2. 核心功能演示查看特定服务器的工具列表mcporter list kali --schema调用简单工具# 检查服务器健康状态 mcporter call kali.server_health调用带参数的工具# Nmap 扫描 mcporter call kali.nmap_scan target:192.168.1.100 scan_type:"-sV"3. 代码讲解mcporter 的基本调用语法为：mcporter call <服务器名>.<工具名> [参数名:值 ...]参数格式使用 key:value 的形式，多个参数用空格分隔。五、配置管理1. 配置文件格式mcporter.json 配置文件示例：{ "mcpServers": { "nagios-mcp": { "url": "http://192.168.124.47:63001/sse" }, "kali": { "url": "http://kali.mcp.op123.ren/sse" } } }2. 常见配置问题JSON 格式错误配置文件必须符合标准 JSON 格式，注意：对象最后一个属性后不能有逗号字符串必须用双引号键名必须用双引号错误示例：{ "kali": { "url": "http://kali.mcp.op123.ren/sse" }, }正确示例：{ "kali": { "url": "http://kali.mcp.op123.ren/sse" } }六、实战案例1. kali MCP 服务器工具调用kali 服务器提供了 12 个渗透测试工具，以下是常用示例。Nmap 端口扫描# 基本版本检测扫描 mcporter call kali.nmap_scan target:192.168.1.100 scan_type:"-sV" # 指定端口范围 mcporter call kali.nmap_scan target:192.168.1.100 scan_type:"-sV" ports:"22,80,443" # 快速扫描前 1000 端口 mcporter call kali.nmap_scan target:192.168.1.100 scan_type:"-sS" ports:"1-1000"Gobuster 目录扫描# 基本目录扫描 mcporter call kali.gobuster_scan url:"http://example.com" mode:dir # 使用自定义字典 mcporter call kali.gobuster_scan url:"http://example.com" mode:dir wordlist:"/path/to/wordlist.txt"Nikto Web 漏洞扫描mcporter call kali.nikto_scan target:"http://example.com"SQLMap SQL 注入检测mcporter call kali.sqlmap_scan url:"http://example.com/login.php?id=1"Metasploit 模块执行# 列出可用的 exploits mcporter call kali.execute_command command:"msfconsole -x 'show exploits'" # 执行特定模块 mcporter call kali.metasploit_run module:"exploit/windows/smb/ms17_010_eternalblue"Hydra 密码破解# SSH 暴力破解 mcporter call kali.hydra_attack target:192.168.1.100 service:ssh username:admin password_file:"/path/to/wordlist.txt"John the Ripper 密码破解# 使用默认字典破解哈希 mcporter call kali.john_crack hash_file:"/path/to/hashes.txt"WPScan WordPress 扫描mcporter call kali.wpscan_analyze url:"http://example.com"Enum4linux Samba 枚举mcporter call kali.enum4linux_scan target:192.168.1.100执行任意命令# 查看系统信息 mcporter call kali.execute_command command:"uname -a" # 查看网络配置 mcporter call kali.execute_command command:"ifconfig"2. 其他服务器示例web-search-prime 搜索mcporter call web-search-prime.web_search search_query:"技术文档"web-reader 网页阅读mcporter call web-reader.webReader url:"https://example.com"七、命令参考1. 核心命令命令说明示例list列出服务器或工具mcporter list [name] [--schema]call调用工具mcporter call [key=value ...]auth完成 OAuth 认证mcporter auth <server \url>config管理配置mcporter config [options]daemon管理守护进程mcporter daemon <start\stop\status>2. 全局选项选项说明默认值--config指定配置文件路径./config/mcporter.json--log-level日志级别warn--oauth-timeoutOAuth 超时时间（毫秒）600003. 生成器工具生成独立 CLImcporter generate-cli --server <name> --compile ./my-cli生成 TypeScript 客户端mcporter emit-ts <server> --mode client八、常见问题1. 安装问题权限错误错误信息：EACCES: permission denied解决方案：使用 sudo 安装sudo npm install -g mcporter2. 配置问题配置文件解析失败错误信息：Expected double-quoted property name in JSON解决方案：检查 JSON 格式，删除对象末尾多余的逗号服务器显示不健康排查步骤：检查服务器 URL 是否正确确认服务器是否在线检查网络连接查看超时设置3. 调用问题工具未找到错误信息：Tool not found解决方案：使用 --schema 查看可用工具mcporter list <server> --schema参数错误错误信息：Invalid parameters解决方案：使用 --all-parameters 查看完整参数列表mcporter list <server> --schema --all-parameters九、注意事项安全测试必须在获得明确授权的前提下进行kali MCP 服务器提供的工具仅供授权安全测试、CTF 比赛和安全研究使用远程 MCP 服务器可能需要身份验证或网络访问权限部分工具执行时间较长，请耐心等待结果建议在测试环境中先验证工具调用，再用于生产场景参考资料mcporter 官方仓库MCP 协议规范
用逗号前缀管理自定义命令行脚本
用逗号前缀管理自定义命令行脚本一、概述1. 问题背景A. 痛点分析许多 Unix/Linux 用户习惯在 home 目录下创建 ~/bin 目录，存放自定义的 shell 脚本和工具，并将其添加到 PATH 环境变量中。这种方式可以方便地扩展系统命令，但存在一个隐患：自定义脚本名可能与系统命令冲突。B. 冲突风险系统命令通常采用小写字母的短名称，自定义脚本往往也遵循类似命名风格。当系统更新或安装新软件时，可能会添加与自定义脚本同名的命令，导致冲突。在 Debian 等发行版中，这个问题尤为突出。例如，一台普通的 Ubuntu 笔记本电脑就有超过 21,000 个可用命令：$ apt-file search -x '^/usr/bin/[^/]*$' | wc -l 217332. 解决思路需要一种命名约定，满足以下要求：便于输入，不需要使用 Shift 键不会被系统命令采用对 shell 和文件系统没有特殊含义二、字符可用性分析1. 字符筛选过程根据"易于输入"原则，候选字符必须在不按 Shift 键的情况下可用。经过系统分析：字符类型是否可用原因小写字母 a-z❌系统命令主要使用这些字符括号 []❌shell 通配符特殊含义反斜杠 \❌shell 转义字符冒号 :❌shell 特殊字符反引号 `❌命令替换特殊含义单引号 '❌shell 引用特殊含义斜杠 /❌路径分隔符，不能出现在文件名中点 .❌文件名中以点开头表示隐藏文件2. 最终选择经过筛选，只剩下一个字符：逗号（,）快速测试证实，逗号完全满足需求：所有工具和 shell 都将其视为普通的文件名字符没有特殊含义或副作用输入方便，无需按 Shift 键三、实施方案1. 命名约定为所有自定义脚本添加逗号前缀：# 原来的命令 myscript backup find # 使用逗号前缀 ,myscript ,backup ,find2. Tab 补全优势使用逗号前缀后，可以轻松浏览所有自定义命令。只需输入逗号并按 Tab 键：$ ,«tab» ,complete-scp ,go-thpgp ,range ,complete-ssh ,gr ,svn-store-password ,coreoff ,hss ,umount ,coreon ,mount-thpgp ,find ,mount-twt这种方式的优点：快速列出所有自定义命令避免与系统命令混淆提示符清晰，易于识别3. 实施步骤A. 创建 ~/bin 目录mkdir -p ~/binB. 添加到 PATH在 ~/.bashrc 或 ~/.zshrc 中添加：export PATH="$HOME/bin:$PATH"C. 重命名现有脚本# 将现有脚本移动到逗号前缀 mv ~/bin/myscript ~/bin/,myscript mv ~/bin/backup ~/bin/,backupD. 创建新脚本时使用逗号前缀# 创建新脚本 cat > ~/bin/,mycommand << 'EOF' #!/bin/bash # 脚本内容 echo "My custom command" EOF chmod +x ~/bin/,mycommand四、原理分析1. Shell 对逗号的处理在 POSIX shell（bash、zsh 等）中，逗号没有被赋予特殊含义。它是普通字符，可以在文件名中自由使用。graph TD A[用户输入命令] --> B{解析命令名} B --> C{是否以逗号开头} C -->|是| D[在 ~/bin 中查找] C -->|否| E[在 PATH 全路径查找] D --> F[执行自定义脚本] E --> G[执行系统命令]2. Tab 补全机制当用户输入逗号并按 Tab 键时：Shell 识别逗号为普通字符搜索 PATH 中所有以逗号开头的可执行文件显示匹配的命令列表由于系统命令从不使用逗号开头，这个列表只包含用户自定义的脚本。3. 可移植性逗号前缀方案在各种 Unix-like 系统中都经过验证：Linux（Debian、Ubuntu、RedHat 等）macOSBSD（FreeBSD、OpenBSD）其他 POSIX 兼容系统五、最佳实践1. 命令命名建议虽然使用逗号前缀可以避免冲突，但仍然建议：使用描述性名称：,backup-database 而非 ,bd保持一致性：相同功能的脚本使用相似的命名模式避免过长：虽然 Tab 补全有帮助，但过长的名称影响可读性2. 脚本组织对于大量脚本，可以考虑进一步分类：# 按功能分类 ,git/ ,git/,push-all ,git/,pull-all ,backup/ ,backup/,database ,backup/,files3. 文档说明在每个脚本中添加注释说明用途：#!/bin/bash # ,sync-files: 同步工作目录到远程服务器 # 用法: ,sync-files [source] [destination] rsync -avz --delete "$1" "$2"六、优势总结1. 避免命名冲突与系统命令完全正交未来系统更新不会影响自定义命令多个用户的自定义脚本不会相互干扰2. 提高可用性Tab 补全快速列出所有自定义命令视觉上易于区分自定义和系统命令输入方便，无需特殊按键3. 长期稳定作者使用此方案超过十年，证明其稳定性适用于各种 Unix-like 系统不会因系统更新而失效七、注意事项1. 兼容性逗号作为文件名字符在所有现代文件系统中都是合法的。但如果需要与非常老的系统交互，建议验证兼容性。2. 脚本shebang确保脚本开头有正确的 shebang：#!/bin/bash #!/usr/bin/env python3 #!/usr/bin/perl3. 执行权限不要忘记为脚本添加执行权限：chmod +x ~/bin/,myscript参考资料Start all of your commands with a comma
Claude 垃圾文件清理脚本技术文档一、概述1. 简介A. 是什么cleanup.sh 是一个专为 Claude Code CLI 设计的自动化垃圾文件清理脚本，用于清理运行过程中产生的各类临时文件、历史记录和缓存数据，释放磁盘空间。B. 为什么需要Claude Code 在日常使用中会产生大量临时文件，包括调试日志、会话环境、任务列表、备份文件等。这些文件随着时间积累会占用大量磁盘空间，但其中大部分历史文件已无实际保留价值。定期清理这些文件可以：释放磁盘空间提升文件系统性能保持工作目录整洁C. 功能特点按保留数量策略清理各目录支持预览模式，可预先查看删除内容完整的统计报告（释放空间、删除文件数）集成日志记录功能安全的文件删除机制2. 前置知识A. 必备技能基本 Linux 命令行操作Bash 脚本基础理解B. 推荐知识了解 Claude Code 目录结构熟悉 cron 定时任务配置二、脚本架构1. 目录结构graph TB A[Claude Home] --> B[scripts/] A --> C[lib/] A --> D[logs/] A --> E[各清理目标目录] B --> B1[cleanup.sh] C --> C1[logger.sh] C --> C2[rsync-config.sh] D --> D1[operations_YYYYMMDD.log] E --> E1[debug/] E --> E2[file-history/] E --> E3[todos/] E --> E4[backups/]2. 工作原理flowchart TD A[启动脚本] --> B{检查运行模式} B -->|预览模式| C[计算待删除文件] B -->|执行模式| D[执行清理操作] C --> E[生成预览报告] D --> F[记录操作日志] E --> G[输出统计报告] F --> G G --> H[结束]3. 清理策略脚本采用基于保留数量的清理策略，各目录保留规则如下：目录保留策略保留数量清理依据debug/按文件数量3 个修改时间倒序file-history/按会话数量50 个修改时间倒序session-env/按会话数量20 个修改时间倒序todos/按文件数量200 个修改时间倒序shell-snapshots/按文件数量10 个修改时间倒序plans/按文件数量20 个修改时间倒序transcripts/按文件数量10 个修改时间倒序backups/按文件数量1 个修改时间倒序paste-cache/全部清理0 个无条件删除根目录杂项按天数30 天文件修改时间三、核心实现1. 配置管理脚本使用关联数组（Associative Array）管理配置参数：declare -A CONFIG=( [debug_keep]=3 [history_keep]=50 [session_keep]=20 [todos_keep]=200 [snapshots_keep]=10 [plans_keep]=20 [transcripts_keep]=10 [backups_keep]=1 [old_file_days]=30 )配置项命名规范：<目录前缀>_keep 表示保留数量，old_file_days 表示天数阈值。2. 空间计算calculate_space 函数使用系统命令获取文件或目录大小：sequenceDiagram participant C as calculate_space participant D as du/stat 命令 participant A as awk C->>D: 检查路径类型 alt 目录 D->>C: 返回 du -sk 结果 else 文件 D->>C: 返回 stat -c%s 结果 end C->>A: 提取数值并转换为字节 A->>C: 返回字节数核心实现：calculate_space() { local path="$1" if [ -d "$path" ]; then du -sk "$path" 2>/dev/null | awk '{print $1 * 1024}' elif [ -f "$path" ]; then stat -c%s "$path" 2>/dev/null || echo 0 else echo 0 fi }3. 按数量清理clean_by_count 函数实现基于保留数量的文件清理：flowchart TD A[开始] --> B[目录是否存在?] B -->|否| C[返回] B -->|是| D[计算清理前空间] D --> E[使用 find 统计文件数] E --> F[计算需删除数量] F --> G{需删除?} G -->|否| C G -->|是| H{预览模式?} H -->|是| I[列出待删除文件] H -->|否| J[按时间排序后删除] I --> K[计算清理后空间] J --> L[记录日志] L --> K K --> M[更新统计并输出]关键技术点：使用 find 命令按修改时间排序：find "$target_dir" -maxdepth 1 -type f -printf '%T@ %p\n' 2>/dev/null | \ sort -rn | \ tail -n +$((keep_count + 1)) | \ cut -d' ' -f2-防止 set -e 导致脚本退出：TOTAL_DELETED=$((TOTAL_DELETED + delete_count)) || true TOTAL_FREED=$((TOTAL_FREED + freed)) || true CLEANED_DIRS=$((CLEANED_DIRS + 1)) || true4. 特殊清理函数clean_paste_cache：清空粘贴缓存目录（全部删除）clean_root_misc：清理根目录杂项文件（按天数）四、使用方法1. 基本用法查看帮助信息：/home/lab/.claude/scripts/cleanup.sh --help预览模式（不实际删除）：/home/lab/.claude/scripts/cleanup.sh --dry-run执行清理：/home/lab/.claude/scripts/cleanup.sh自动确认并详细输出：/home/lab/.claude/scripts/cleanup.sh -y -v2. 命令行选项选项长选项说明-d--dry-run预览模式，不实际删除文件-y--yes自动确认，不询问-v--verbose详细输出，启用 DEBUG 日志级别-h--help显示帮助信息3. 输出示例预览模式输出：======================================== Claude 垃圾文件清理工具 ======================================== 工作目录: /home/lab/.claude 模式: 预览 (DRY-RUN) ======================================== [DRY-RUN] debug: 将删除 8 个文件 - 7d380f20-16eb-48da-ada5-063d12dc7c78.txt - c436eebe-58e5-4fa1-ab3d-f9a484b97330.txt ... debug: 1MB → 1MB [释放: 0B] ======================================== 清理完成报告 ======================================== 释放空间: 0B 删除文件数: 2540 清理目录数: 9 ========================================执行模式输出：======================================== Claude 垃圾文件清理工具 ======================================== 工作目录: /home/lab/.claude 模式: 执行 ======================================== debug: 1.2M → 584K [释放: 600K] todos: 8.1M → 1.1M [释放: 7MB] ... ======================================== 清理完成报告 ======================================== 释放空间: 21MB 删除文件数: 2540 清理目录数: 9 ========================================五、依赖库1. logger.sh日志库提供统一的日志功能：classDiagram class logger_sh { +LOG_DIR: string +LOG_FILE: string +LOG_LEVEL: string +LOG_LEVELS: map +log(level, message) +cleanup_logs() +rotate_log() }核心功能：日志级别控制（DEBUG/INFO/WARN/ERROR）日志文件按日期分割日志自动轮转（单文件超过 10MB）带颜色的控制台输出2. rsync-config.sh配置库提供共享配置：classDiagram class rsync_config_sh { +RED: string +GREEN: string +BLUE: string +NC: string +EXCLUDE_ARGS: array +RSYNC_OPTIONS: string +get_script_dir() +test_ssh_connection() +do_rsync() }六、定时任务配置1. cron 配置编辑 crontab：crontab -e添加定时任务：# 每周日凌晨 2 点执行清理 0 2 * * 0 /home/lab/.claude/scripts/cleanup.sh --yes # 每天凌晨 3 点执行清理 0 3 * * * /home/lab/.claude/scripts/cleanup.sh --yes # 每月 1 号凌晨 2 点执行清理 0 2 1 * * /home/lab/.claude/scripts/cleanup.sh --yes2. 日志轮转日志文件会自动清理 30 天前的记录：cleanup_logs() { find "$LOG_DIR" -name "operations_*.log" -mtime +$LOG_MAX_DAYS -delete }七、故障排查1. 常见问题问题原因解决方法脚本无法执行缺少执行权限运行 chmod +x cleanup.sh清理后空间未释放其他进程占用文件重启相关服务或系统日志未记录LOG_DIR 不存在脚本会自动创建目录find 命令报错系统不支持 -printf使用 GNU findutils2. 调试方法启用详细输出：/home/lab/.claude/scripts/cleanup.sh -v --dry-run查看日志文件：cat /home/lab/.claude/logs/operations_$(date +%Y%m%d).log手动测试清理函数：# 只清理 debug 目录，保留 3 个文件 find /home/lab/.claude/debug -maxdepth 1 -type f -printf '%T@ %p\n' | \ sort -rn | tail -n +4 | cut -d' ' -f2-八、扩展与定制1. 修改保留数量编辑脚本中的 CONFIG 关联数组：declare -A CONFIG=( [debug_keep]=5 # 修改为保留 5 个 [todos_keep]=500 # 修改为保留 500 个 ... )2. 添加新的清理目录在 main 函数中添加：clean_by_count "new-directory" 100 # 保留 100 个文件3. 自定义清理规则创建自定义清理函数：clean_custom() { local target_dir="${CLAUDE_HOME}/custom-dir" if [ ! -d "$target_dir" ]; then return 0 fi # 自定义清理逻辑 find "$target_dir" -name "*.tmp" -mtime +7 -delete log INFO "已清理 custom-dir 中的临时文件" }九、最佳实践1. 使用建议首次使用前先运行 --dry-run 预览定期（每周或每月）执行清理重要数据备份后再执行清理根据实际使用情况调整保留数量2. 安全注意事项脚本不会删除 settings.json 和 .credentials.jsonskills/、plugins/、lib/ 等核心目录不会被清理建议在配置文件中明确排除重要目录3. 性能优化使用 find -printf 而非 ls -t，性能更优使用管道并行处理，提高清理速度大量文件清理时建议分批进行参考资料Bash Guide for BeginnersGNU Findutils Manual
fd 文件查找工具快速入门指南一、概述1. 简介A. 是什么fd 是一个用 Rust 编写的命令行文件查找工具，旨在成为传统 Unix find 命令的简单、快速且用户友好的替代品。它不追求支持 find 的全部强大功能，而是为大多数使用场景提供合理的默认配置。B. 为什么学速度极快：并行目录遍历，比传统 find 快 10-20 倍语法简洁：fd PATTERN 即可，无需记忆复杂的 find 参数智能默认：自动忽略隐藏文件和 gitignore 中的文件彩色输出：像 ls 一样用颜色区分不同文件类型易用性强：支持正则表达式和 glob 模式匹配C. 学完能做什么快速在文件系统中查找文件和目录按扩展名、文件类型、大小等条件过滤批量执行命令处理搜索结果与 fzf、ripgrep 等工具集成使用2. 前置知识A. 必备技能基本 Linux/Unix 命令行操作了解文件系统目录结构概念B. 推荐知识正则表达式基础熟悉 shell 通配符二、环境准备1. 系统要求Linux：Ubuntu、Debian、Fedora、Arch 等macOS：10.15+Windows：10/112. 安装步骤Ubuntu/Debian：# Ubuntu 19.04+ 或 Debian Buster+ apt install fd-find # 创建软链接以便使用 fd 命令 ln -s $(which fdfind) ~/.local/bin/fdmacOS：# 使用 Homebrew brew install fd # 或使用 MacPorts port install fdWindows：# 使用 Scoop scoop install fd # 或使用 Chocolatey choco install fd # 或使用 Winget winget install sharkdp.fd从源码编译：# 使用 cargo 安装 cargo install fd-find # 或从源码构建 git clone https://github.com/sharkdp/fd cd fd cargo build cargo install --path .3. 验证安装fd --version三、核心概念1. 基本术语模式（Pattern）：用于匹配文件名的正则表达式或 glob 模式智能大小写（Smart Case）：默认不区分大小写，包含大写字母时自动区分并行遍历：同时搜索多个目录以提高速度2. 工作原理graph TB A[fd 命令] --> B{解析参数} B --> C[并行遍历目录] C --> D{应用过滤规则} D --> E{正则/glob 匹配} E --> F{检查隐藏文件} F --> G{检查 gitignore} G --> H[输出结果]3. 与 find 的对比特性fdfind基本语法fd PATTERNfind -iname 'PATTERN'速度并行遍历，极快串行遍历，较慢默认行为忽略隐藏和 gitignore 文件搜索所有文件大小写智能判断需手动指定彩色输出默认支持需额外配置四、快速上手1. Hello World 示例# 查找包含 'netfl' 的文件 fd netfl # 输出： # Software/python/imdb-ratings/netflix-details.py2. 核心功能演示简单搜索：# 搜索包含某个模式的文件 fd test # 指定搜索目录 fd passwd /etc正则表达式搜索：# 搜索以 x 开头、rc 结尾的文件 cd /etc fd '^x.*rc$' # 输出： # X11/xinit/xinitrc # X11/xinit/xserverrc列出所有文件：# 递归列出当前目录所有文件 fd # 列出指定目录的所有文件 fd . /path/to/dir五、进阶内容1. 常用功能按扩展名搜索：# 查找所有 Markdown 文件 fd -e md # 查找多个扩展名 fd -e rs -e cpp mod # 组合模式和扩展名 fd -e rs mod精确匹配文件名：# 使用 glob 模式精确匹配 fd -g libc.so /usr # 输出： # /usr/lib32/libc.so # /usr/lib/libc.so搜索隐藏文件：# 默认不搜索隐藏文件 fd pre-commit # 搜索隐藏文件 fd -H pre-commit # 输出： # .git/hooks/pre-commit.sample忽略 gitignore：# 默认遵循 .gitignore fd num_cpu # 不遵循 .gitignore fd -I num_cpu完全无限制搜索：# 搜索所有文件（包括隐藏和被忽略的） fd -u pattern # 等同于 fd -HI pattern2. 最佳实践A. 搜索完整路径默认只匹配文件名，使用 -p 选项匹配完整路径：fd -p -g '**/.git/config' fd -p '.*/lesson-\d+/[a-z]+.(jpg|png)'B. 限定搜索深度# 只搜索当前目录（不递归） fd -d 1 pattern # 最多递归 3 层 fd -d 3 patternC. 按文件类型过滤# 只搜索文件 fd -tf pattern # 只搜索目录 fd -td pattern # 只搜索符号链接 fd -tl pattern # 只搜索可执行文件 fd -tx pattern # 只搜索空文件 fd -te patternD. 按文件大小过滤# 搜索大于 100MB 的文件 fd -S +100M # 搜索小于 1KB 的文件 fd -S -1k # 搜索大小在 1MB-1GB 之间的文件 fd -S +1M -S -1GE. 按修改时间过滤# 搜索最近 7 天修改的文件 fd --changed-within 7d # 搜索超过 30 天未修改的文件 fd --changed-before 30d # 搜索最近 1 小时修改的文件 fd --changed-within 1h3. 性能优化fd 已经针对性能进行了优化。根据官方基准测试，在包含约 400 万文件的系统中：fd 比 find -iregex 快约 23 倍fd 比 find -iname 快约 13 倍性能优势主要来自：并行目录遍历高效的正则表达式引擎智能缓存策略六、实战案例1. 场景描述在日常开发和运维工作中，需要快速查找并批量处理文件。2. 实现步骤场景一：批量解压文件# 查找所有 zip 文件并解压 fd -e zip -x unzip场景二：格式化代码# 查找所有 .h 和 .cpp 文件并格式化 fd -e h -e cpp -x clang-format -i场景三：批量打开文件# 在编辑器中打开所有测试文件 fd -g 'test_*.py' -X vim场景四：计算文件校验和# 计算所有文件的 MD5 校验和 fd -tf -x md5sum > file_checksums.txt场景五：文件类型转换# 将所有 jpg 文件转换为 png fd -e jpg -x convert {} {.}.png场景六：搜索并编辑# 在所有 C++ 文件中搜索特定内容 fd -e cpp -e cxx -e h -e hpp -X rg 'std::cout'3. 完整代码示例占位符语法fd 提供了类似 GNU Parallel 的占位符语法：# {} - 完整路径 fd -x echo {} # {.} - 去掉扩展名的路径 fd -x echo {.} # {/} - 文件名（含扩展名） fd -x echo {/} # {/.} - 文件名（不含扩展名） fd -x echo {/.} # {//} - 父目录 fd -x echo {//}并行控制# 默认并行执行 fd -x command # 限制并发数为 4 fd -j 4 -x command # 串行执行 fd -j 1 -x command批量执行# -x 为每个结果单独执行命令（并行） fd -e zip -x unzip # -X 一次性对所有结果执行命令 fd -g 'test_*.py' -X vim七、常见问题1. 安装问题Q: Ubuntu 上安装后命令是 fdfind 而不是 fdA: 创建软链接即可：ln -s $(which fdfind) ~/.local/bin/fdQ: Windows 上找不到 fd 命令A: 确保 Scoop/Chocolatey 安装目录已添加到 PATH 环境变量。2. 配置问题Q: 如何永久设置排除模式A: 创建 .fdignore 文件或全局配置文件：# 用户全局配置（Linux/macOS） ~/.config/fd/ignore # 用户全局配置（Windows） %APPDATA%\fd\ignore示例配置：/mnt/external-drive *.bak *.tmp node_modules/Q: 如何显示文件详细信息A: 使用 -l 选项：fd -l pattern3. 运行问题Q: fd 找不到我的文件A: 检查以下几点：文件是否在隐藏目录中，使用 -H 选项是否被 .gitignore 排除，使用 -I 选项是否需要匹配完整路径，使用 -p 选项Q: 正则表达式不生效A: 确保用单引号包裹正则表达式：fd '^[A-Z][0-9]+$'Q: 如何删除匹配的文件A: 使用 -X 选项配合 rm：# 删除所有 .DS_Store 文件 fd -H '^\.DS_Store$' -tf -X rm # 交互式删除（安全模式） fd -H '^\.DS_Store$' -tf -X rm -i八、工具集成1. 与 fzf 集成# 设置 fzf 使用 fd export FZF_DEFAULT_COMMAND='fd --type file' export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" # 带颜色的输出 export FZF_DEFAULT_COMMAND="fd --type file --color=always" export FZF_DEFAULT_OPTS="--ansi"2. 与 tree 集成# 将 fd 输出格式化为树形结构 fd | tree --fromfile # 按扩展名过滤并显示为树 fd --extension rs | tree --fromfile3. 与 rofi 集成# 在 rofi 中创建可搜索的 PDF 文件列表 fd --type f -e pdf . $HOME | rofi -dmenu -i -p FILES -multi-select | xargs -I {} xdg-open {}4. 与 xargs 集成# 使用 NULL 分隔符处理特殊文件名 fd -0 -e rs | xargs -0 wc -l九、命令选项速查常用选项-H, --hidden # 搜索隐藏文件 -I, --no-ignore # 不遵循 .gitignore -s, --case-sensitive # 区分大小写 -i, --ignore-case # 不区分大小写 -g, --glob # glob 模式搜索 -a, --absolute-path # 显示绝对路径 -l, --list-details # 显示详细信息 -L, --follow # 跟随符号链接 -p, --full-path # 匹配完整路径 -d, --max-depth <n> # 限制搜索深度 -t, --type <type> # 按类型过滤 -e, --extension <ext> # 按扩展名过滤 -S, --size <size> # 按大小过滤 -x, --exec <cmd> # 对每个结果执行命令 -X, --exec-batch <cmd> # 批量执行命令 -j, --threads <n> # 并发线程数 -u, --unrestricted # 无限制搜索参考资料fd - GitHub Repository
Linux环境变量问题技术分析一、概述1. 问题背景在日常Linux运维和开发工作中，环境变量相关的问题是导致脚本执行失败的主要原因之一。这类问题通常表现为：命令在交互式终端中正常执行，但通过 crontab、SSH 远程执行或自动化工具执行时却报错找不到命令。2. 核心问题脚本在命令行测试正常，放入 crontab 后报错找不到命令SSH 远程执行命令时环境变量与本地登录不同Docker 容器中环境变量传递问题Bash 与 Sh 语法兼容性问题3. 影响范围自动化脚本执行失败定时任务无法正常运行容器化应用启动异常跨平台脚本兼容性问题二、问题分析1. Login Shell 与 Non-Login ShellA. 核心区别Linux Shell 分为两种模式：Login Shell（登录式 Shell）和 Non-Login Shell（非登录式 Shell），它们加载环境变量的顺序不同。B. 环境变量加载顺序graph TD subgraph Login Shell A1["/etc/profile"] --> A2["~/.bash_profile"] A2 --> A3["~/.bashrc"] A3 --> A4["/etc/bashrc"] end subgraph Non-Login Shell B1["~/.bashrc"] --> B2["/etc/bashrc"] end C["用户登录"] --> Login D["SSH远程执行命令"] --> Non-Login E["Crontab执行"] --> Non-Login F["脚本调用"] --> Non-LoginC. 关键差异Login Shell 加载顺序：① /etc/profile ② ~/.bash_profile ③ ~/.bashrc ④ /etc/bashrcNon-Login Shell 加载顺序：① ~/.bashrc ② /etc/bashrc/etc/profile 中包含 pathmunge 函数，负责将 /usr/sbin、/usr/local/sbin 等路径添加到 PATH 变量中。Non-Login Shell 由于跳过了 /etc/profile 的加载，导致这些路径缺失。2. 实际场景分析A. SSH 远程执行命令# 直接登录后执行（Login Shell） ssh user@ip ip a # 正常执行 # 远程直接执行命令（Non-Login Shell） ssh user@ip "ip a" # 报错：bash: ip: command not found原因分析：Login Shell：PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbinNon-Login Shell：PATH=/usr/local/bin:/usr/binip 命令位于 /usr/sbin 下，Non-Login Shell 的 PATH 中不包含该路径。B. Crontab 定时任务脚本在命令行测试正常，放入 crontab 后报错找不到命令。这是因为：命令行执行使用当前用户的完整环境变量Crontab 执行时的环境变量被 sudo 修改（如果使用 sudo）sudo 默认会重置环境变量3. Bash 与 Sh 的区别A. 命令差异命令/特性BashSh (POSIX)source内建命令不支持（用 . 代替）语法扩展支持数组等仅 POSIX 标准 B. 系统链接差异CentOS：/usr/bin/sh → /usr/bin/bash（sh 等同于 bash）Ubuntu：/usr/bin/sh → /usr/bin/dash（sh 是独立的 dash）这就是为什么在 CentOS 上用 sh 执行的脚本在 Ubuntu 上可能报语法错误。三、解决方案1. Crontab 环境变量问题A. 使用 sudo -E 参数# 在 crontab 中使用 sudo -E /path/to/script.sh-E 参数（--preserve-env）可以保留当前用户的环境变量。B. 脚本中显式加载环境变量#!/bin/bash # 在脚本开头添加 source /etc/profile source ~/.bashrcC. 脚本使用 login shell#!/bin/bash --login2. SSH 远程执行问题A. 创建全局环境变量文件在 /etc/profile.d/ 下创建自定义环境变量文件：# /etc/profile.d/my_bashenv.sh pathmunge () { if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then if [ "$2" = "after" ] ; then PATH=$PATH:$1 else PATH=$1:$PATH fi fi } pathmunge /sbin pathmunge /usr/sbin pathmunge /usr/local/sbin pathmunge /usr/local/bin/etc/bashrc 会自动加载 /etc/profile.d/ 下的所有 *.sh 文件。B. 使用 SSH -t 参数ssh -t user@ip "command"-t 参数强制分配伪终端（TTY），可以触发 login shell。3. Docker 环境变量问题A. 问题现象docker run 时传入的环境变量，root 用户可见通过 crond 以 admin 用户执行时无法读取B. 解决方案在 Docker 镜像构建时修改 /etc/bashrc 和 ~/.bashrc：将 . /etc/bashrc 改为 source /etc/bashrc确保 /etc/profile.d/dockerenv.sh 被正确加载4. 通用最佳实践A. 脚本开头统一使用#!/bin/bash --login set -euxo pipefail--login：确保使用 login shell-e：遇到错误立即退出-u：使用未定义变量时报错-o pipefail：管道中任何命令失败都返回失败状态-x：打印执行的命令（调试用）B. 使用绝对路径在脚本中尽量使用命令的绝对路径：/usr/bin/docker instead of docker /usr/sbin/ip instead of ipC. 显式设置 PATH#!/bin/bash export PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:$PATH四、深入原理1. 环境变量继承机制A. 进程创建与变量继承sequenceDiagram participant P as 父进程 participant E as 环境变量 participant S as 子进程 P->>E: export VAR=value E->>E: VAR 变为环境变量 P->>S: fork + exec E->>S: 继承环境变量 S->>S: 可访问 VAR Note over P,S: 未 export 的自定义变量不会被继承B. export 命令作用默认：子进程仅继承父进程的环境变量export：将自定义变量转换为环境变量，使子进程可继承2. Shell 执行方式差异A. 三种执行方式对比方式进程环境变量变量作用域source script.sh当前进程共享变量在当前 shell 生效bash script.sh子进程独立变量不带回父 shell./script.sh子进程独立变量不带回父 shellB. 验证实例# 测试脚本 test.sh echo $$ # 显示进程 ID # 执行结果 echo $$ # 2299（父进程） source test.sh # 2299（同一进程） bash test.sh # 4037（新进程） ./test.sh # 4040（新进程）3. Su 命令的差异A. su 与 su - 的区别su：只切换用户身份，Shell 环境保持不变su -：切换用户身份和 Shell 环境（包括工作目录和环境变量）B. 实际影响su admin # 重新加载 ~/.bashrc # 工作目录不变 su - admin # 不重新加载 ~/.bashrc # 切换到 admin 的 home 目录五、常见问题与排查1. 命令找不到A. 排查步骤# 1. 确认命令位置 which ip type -a ip # 2. 检查 PATH echo $PATH env | grep PATH # 3. 确认当前 shell 类型 echo $0 echo $-B. 判断标准$0 包含 -bash 表示 login shell$- 包含 i 表示交互式 shell不含 i 和 - 的是非交互式非登录 shell2. History 命令无输出A. 原因history 是 bash 内部命令，在非交互式环境中默认关闭。B. 解决方案# 在脚本中开启 set -o history3. Source 命令找不到A. 错误信息source: not foundB. 原因使用 sh 执行脚本，但 source 是 bash 内建命令。C. 解决方案使用 bash 执行脚本或将 source 改为 .（POSIX 兼容）六、Shell 调试技巧1. 启动参数参数作用-n只检查语法，不执行-v执行前输出每行语句-x执行后输出每个命令2. 使用示例bash -n script.sh # 语法检查 bash -v script.sh # 显示执行过程 bash -x script.sh # 调试模式七、参考资料参考资料Linux环境变量问题汇总 - planteggBash Startup Files - GNU ManualBash Reference Manual
Linux 用户活动监控工具 psacct 与 acct 使用教程一、概述1. 简介A. 是什么psacct 和 acct 是 Linux 系统中用于监控用户活动的开源工具。这些工具在后台运行，持续跟踪系统中每个用户的活动以及所消耗的资源。B. 为什么学多用户服务器管理需要了解用户行为安全审计和问题排查的基础工具资源管理和容量规划的数据来源系统管理员必备的监控技能C. 学完能做什么查看用户登录时长和连接时间统计追踪用户执行的所有命令监控系统资源消耗情况生成用户活动报告用于审计2. 前置知识A. 必备技能基本 Linux 命令操作了解 Linux 用户和权限概念熟悉 systemctl 服务管理命令B. 推荐知识Linux 进程管理基础系统日志和日志轮转概念二、环境准备1. 系统要求Linux 发行版：RHEL/CentOS/Fedora 或 Ubuntu/Debianroot 或 sudo 权限磁盘空间：至少 500MB 用于日志存储2. 安装步骤RHEL/CentOS/Fedora 系统：sudo yum install psacct # 或在新系统上使用 dnf sudo dnf install psacctUbuntu/Debian 系统：sudo apt install acct其他发行版：# Alpine Linux sudo apk add psacct # Arch Linux sudo pacman -S acct # OpenSUSE sudo zypper install acct3. 启动服务RHEL 系统需要手动启动：# 查看服务状态 sudo systemctl status psacct # 启动服务 sudo systemctl start psacct # 设置开机自启 sudo systemctl enable psacct # 再次查看状态确认 sudo systemctl status psacctDebian 系统会自动启动服务。4. 验证安装# 检查进程日志文件是否创建 ls -lh /var/account/pacct # 查看当前登录统计 ac三、核心概念1. 基本术语psacct/acct：进程 accounting 工具包pacct：进程 accounting 数据文件wtmp：用户登录登出记录文件连接时间：用户登录系统的累计时长2. 工作原理graph TB A[用户登录] --> B[系统记录 wtmp] A --> C[用户执行命令] C --> D[acct 记录进程信息] D --> E[写入 pacct 文件] B --> F[ac 命令读取] E --> G[sa 命令读取] E --> H[lastcomm 命令读取] F --> I[生成统计报告] G --> I H --> I3. 核心命令功能命令功能说明ac显示用户登录/登出统计（连接时间）lastcomm显示用户之前执行的命令accton开启或关闭进程 accountingsa汇总已执行命令的信息last/lastb显示最后登录的用户列表四、快速上手1. 查看总连接时间ac输出示例：total 11299.15这个数字表示所有用户累计连接小时数。2. 按日期查看连接时间ac -d输出示例：Oct 28 total 234.50 Oct 29 total 189.23 Oct 30 total 198.67 Oct 31 total 456.12 Nov 1 total 267.45 Nov 2 total 201.34 Nov 3 total 423.45注意某些日期的异常峰值，需要调查原因。3. 按用户查看连接时间ac -p输出示例：rockylinux 425.61 tecmint 702.29 root 10171.54 total 11299.44可以看到 root 用户的登录时间远超其他用户。4. 查看特定用户连接时间ac ravi输出示例：total 110.31五、进阶内容1. 命令执行统计A. 查看所有命令摘要sa输出包含以下列：第一列：实际执行时间（挂钟时间，分钟）第二列：CPU 时间（系统+用户时间，分钟）第三列：平均 CPU 使用量（以 1k 为单位）第四列：命令名称带星号（*）的命令表示以超级用户权限运行。B. 查看特定用户信息sa -u显示每个用户执行的命令及资源消耗。C. 查看进程统计sa -m显示总进程数和 CPU 分钟数。如果这些数字持续增长，需要调查系统状况。D. 按使用率排序sa -c按百分比显示资源使用情况，帮助识别消耗最多资源的命令。2. 命令历史查询A. 查看用户最后执行的命令lastcomm ravi输出显示用户 ravi 执行的最后命令。B. 限制输出行数lastcomm tecmint | head -n 20只显示最近 20 条命令。C. 搜索特定命令lastcomm ls查看所有 ls 命令的执行记录。D. 安全审计示例lastcomm cat | grep -i "shadow\|passwd"查看谁访问过敏感文件。3. 实战应用场景A. 追踪资源消耗当服务器运行缓慢时，使用 sa -c 识别哪些命令消耗最多 CPU 时间。B. 安全审计使用 lastcomm 审查安全事件前执行的命令，创建比 shell history 更难篡改的审计跟踪。C. 计费和统计报告对于共享主机环境，ac -p 提供用户活动的具体数据用于计费。D. 问题排查当用户声称"我什么都没做"时，可以验证实际执行的命令。六、日志管理1. 日志文件位置主要的 accounting 文件位于 /var/account/pacct2. 日志轮转配置创建 logrotate 配置文件 /etc/logrotate.d/psacct：sudo nano /etc/logrotate.d/psacct添加以下内容：/var/account/pacct { monthly rotate 12 compress notifempty create 0600 root root }配置说明：monthly：每月轮转一次rotate 12：保留 12 个历史文件compress：压缩旧日志notifempty：空文件不轮转create 0600 root root：创建新文件并设置权限七、最佳实践1. 定期检查报告每周查看用户连接时间统计关注异常登录模式监控资源消耗趋势2. 日志保留策略根据合规要求确定保留时间定期备份日志文件确保磁盘空间充足3. 安全建议限制日志文件访问权限（0600）定期审计管理员活动将日志发送到远程日志服务器4. 性能考虑accounting 会带来轻微性能开销高负载系统需要评估影响可以使用 accton 命令临时关闭八、常见问题1. 安装问题Q：psacct 服务无法启动A：检查 /var/account 目录是否存在，权限是否正确2. 配置问题Q：ac 命令没有输出A：确认 psacct 服务已启动，且用户登录过系统3. 运行问题Q：日志文件过大A：配置 logrotate 自动轮转日志九、参考资料ac 命令手册：man acsa 命令手册：man salastcomm 命令手册：man lastcommaccton 命令手册：man accton参考资料How to Monitor Linux User Activity with psacct and acct Tools
Tmux 高效终端工作流配置指南一、概述1. 简介A. 是什么Tmux 是一个终端复用器，允许用户在单个终端窗口中创建、访问和控制多个终端会话。B. 为什么学永久保存终端会话，SSH 断线不丢失工作状态多窗口、多面板高效切换灵活的会话管理和工作流编排C. 学完能做什么搭建个人化的终端工作环境实现工具的快速调用和切换在嵌套 SSH 会话中流畅操作二、核心概念1. 基本术语会话（Session）：tmux 的最高级别组织单位窗口（Window）：会话中的单个标签页面板（Pane）：窗口中的分割区域前缀键（Prefix）：触发 tmux 命令的组合键2. 工作原理graph TB A[终端] --> B[Tmux Server] B --> C[Session 1] B --> D[Session 2] C --> E[Window 1] C --> F[Window 2] E --> G[Pane 1] E --> H[Pane 2] F --> I[Pane 3]3. 进化历程终端工具的发展推动了 tmux 配置的迭代：早期：简单的分屏功能中期：集成 lazygit 等 Git 工具现在：集成 AI 助手弹窗、现代文件管理器等graph LR A[分屏] --> B[+lazygit] B --> C[+AI助手] C --> D[+Yazi] D --> E[完整工具链]三、配置原则1. 前缀键优化默认的 Ctrl-b 按键位置不佳，推荐改用反引号键：反引号键在手位更自然的位置减少手指伸展距离提高频触效率配置示例：# 设置前缀键为 Ctrl-` unbind C-b set -g prefix C-` bind C-` send-prefix2. Popup 快捷调用将常用工具配置为 popup 弹窗，随叫随到：按键触发，显示工具界面关闭后自动回到原工作流不占用固定面板空间sequenceDiagram participant U as 用户 participant T as Tmux participant P as Popup U->>T: 按下快捷键 T->>P: 创建弹窗 P->>U: 显示工具界面 U->>P: 使用工具 U->>P: 关闭弹窗 P->>T: 销毁弹窗 T->>U: 返回原界面3. SSH 嵌套会话处理在多层 SSH 连接中使用 tmux 需要避免按键冲突：外层和内层使用不同的前缀键或者使用按键绑定切换活动会话推荐方案：外层 tmux：Ctrl-`内层 tmux：Ctrl-a或者使用 Ctrl-a a 切换到内层四、配置示例1. 基础配置# 前缀键 set -g prefix C-` unbind C-b bind C-` send-prefix # 索引从 1 开始 set -g base-index 1 setw -g pane-base-index 1 # 鼠标支持 set -g mouse on # 自动重命名窗口 setw -g automatic-rename on # 状态栏 set -g status-interval 1 set -g status-justify left set -g status-bg black set -g status-fg white2. Popup 工具配置# Lazygit popup bind g display-popup -E -w 80% -h 80% lazygit # Yazi 文件管理器 popup bind y display-popup -E -w 80% -h 80% yazi # HTOP 监控 popup bind h display-popup -E -w 80% -h 80% htop # AI 助手 popup bind a display-popup -E -w 80% -h 80% claude-code3. 面板管理# 分割面板 bind | split-window -h -c "#{pane_current_path}" bind - split-window -v -c "#{pane_current_path}" # 在面板间移动 bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R # 调整面板大小 bind -r H resize-pane -L 5 bind -r J resize-pane -D 5 bind -r K resize-pane -U 5 bind -r L resize-pane -R 54. 会话管理# 快速切换会话 bind -r C-s choose-session # 新建会话 bind C new-session -s work # 保存会话 set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-resurrect' set -g @plugin 'tmux-plugins/tmux-continuum' set -g @continuum-restore 'on' set -g @continuum-save-interval '15'五、工作流示例1. 开发工作流启动开发环境的 tmux 会话：# 创建会话 tmux new-session -s dev # 窗口 1：代码编辑 # 窗口 2：Git 操作（lazygit popup） # 窗口 3：服务器监控（htop popup） # 窗口 4：日志查看2. 运维工作流服务器管理的标准布局：# 窗口 1：主操作终端 # 窗口 2：系统监控 # 窗口 3：日志 tail # 窗口 4：备用 SSH3. 工具链集成将常用工具无缝集成到工作流：文件管理：YaziGit 操作：lazygitAI 编程：Claude Code系统监控：htop/btop数据库：cli 客户端 popup六、高级技巧1. 会话脚本化#!/bin/bash # dev-session.sh tmux new-session -d -s dev -n main tmux send-keys -t dev:main 'cd ~/project' Enter tmux new-window -t dev -n git tmux send-keys -t dev:git 'lazygit' Enter tmux new-window -t dev -n monitor tmux send-keys -t dev:monitor 'htop' Enter tmux attach-session -t dev:main2. 自动化插件管理使用 TPM（Tmux Plugin Manager）：# 安装 TPM git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm # 配置插件 set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-sensible' set -g @plugin 'tmux-plugins/tmux-yank' # 安装插件（Prefix + I）3. 跨平台配置确保配置在不同系统上可用：# 检测操作系统 if-shell "uname | grep -q Darwin" \ "set -g status-bg colour234" \ "set -g status-bg colour235" # 兼容不同终端 set -g default-terminal "screen-256color" set -ga terminal-overrides ",xterm-256color:Tc"七、常见问题1. 前缀键冲突问题：内层和外层 tmux 前缀键相同解决：# 方案 1：使用不同前缀 # 外层：Ctrl-` # 内层：Ctrl-a # 方案 2：快速切换 bind-key -n C-a send-prefix2. 复制粘贴问题问题：无法复制 tmux 内容到系统剪贴板解决：# macOS set -g default-command "reattach-to-user-namespace -l $SHELL" bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy" # Linux set -g @plugin 'tmux-plugins/tmux-yank'3. 颜色显示异常问题：终端颜色不正确解决：set -g default-terminal "screen-256color" set -ga terminal-overrides ",xterm-256color:Tc"八、参考资料参考资料Tmux 配置分享 - @xqliu
命令行工具与 Hadoop 集群性能对比技术分析
命令行工具与 Hadoop 集群性能对比技术分析一、概述1. 问题背景Adam Drake 在浏览技术文章时，发现 Tom Hayden 使用 Amazon EMR 和 mrjob 计算 175 万局国际象棋棋谱的胜负统计数据。原始数据约 1.75GB，包含 200 万局棋谱，使用 Hadoop 集群处理耗时约 26 分钟。2. 核心争议Hadoop 集群（7 台 c1.medium 机器）处理时间：26 分钟处理速度：约 1.14MB/秒Adam 质疑：对于这种规模的数据，是否真的需要分布式计算框架3. 技术方案使用 Unix 命令行工具构建流式处理管道，实现相同的数据分析任务。二、数据分析1. 数据格式（PGN 格式）PGN（Portable Game Notation）是国际象棋棋谱的标准格式：[Event "F/S Return Match"] [Site "Belgrade, Serbia Yugoslavia|JUG"] [Date "1992.11.04"] [Round "29"] [White "Fischer, Robert J."] [Black "Spassky, Boris V."] [Result "1/2-1/2"] (棋谱着法...)2. 目标字段只需提取 Result 字段，共 3 种结果：1-0：白方胜0-1：黑方胜1/2-1/2：和棋3. 数据规模Tom Hayden 测试：1.75GB，约 200 万局棋谱Adam Drake 测试：3.46GB，约 400 万局棋谱（2 倍数据量）三、性能对比1. 基准测试Hadoop 方案（7 台机器集群）：处理时间：26 分钟数据量：1.75GB处理速度：约 1.14MB/秒命令行工具方案（单台笔记本电脑）：处理时间：12 秒数据量：3.46GB处理速度：约 270MB/秒性能提升：速度比：235 倍数据量：2 倍综合性能：约 470 倍（按相同数据量计算）2. 性能瓶颈分析A. Hadoop 瓶颈集群启动开销数据序列化与反序列化网络传输开销MapReduce 框架调度开销B. 命令行工具优势流式处理，无需加载全部数据到内存Unix 管道天然并行使用原生编译工具（mawk），性能优异无分布式通信开销四、技术实现1. 初版方案使用 cat、grep、sort、uniq 组合：cat *.pgn | grep "Result" | sort | uniq -c性能：处理时间：70 秒（3.46GB 数据）推算 Hadoop 处理相同数据需要：52 分钟2. 优化方案一：使用 awk引入 awk 替代 sort 和 uniq：cat *.pgn | grep "Result" | awk '{ split($0, a, "-"); res = substr(a[1], length(a[1]), 1); if (res == 1) white++; if (res == 0) black++; if (res == 2) draw++; } END { print white+black+draw, white, black, draw }'原理：split() 以 - 分隔结果字符串substr() 提取胜负标识（1、0、2）统计三种结果数量性能：处理时间：65 秒速度提升：47 倍（相比 Hadoop）瓶颈：grep 单核 CPU 100% 使用3. 优化方案二：并行化 grep使用 find 和 xargs 并行处理：find . -type f -name '*.pgn' -print0 | \ xargs -0 -n1 -P4 grep -F "Result" | \ gawk '{ split($0, a, "-"); res = substr(a[1], length(a[1]), 1); if (res == 1) white++; if (res == 0) black++; if (res == 2) draw++; } END { print NR, white, black, draw }'参数说明：-print0/-0：空字符分隔文件名，处理特殊字符-n1：每个进程处理 1 个文件-P4：并行运行 4 个进程-F：固定字符串匹配（非正则表达式）性能：处理时间：38 秒速度提升：77 倍（相比 Hadoop）4. 优化方案三：移除 grep，纯 awk将过滤逻辑集成到 awk 中：find . -type f -name '*.pgn' -print0 | \ xargs -0 -n4 -P4 awk '/Result/ { split($0, a, "-"); res = substr(a[1], length(a[1]), 1); if (res == 1) white++; if (res == 0) black++; if (res == 2) draw++ } END { print white+black+draw, white, black, draw }' | \ awk '{ games += $1; white += $2; black += $3; draw += $4; } END { print games, white, black, draw }'关键改进：awk 内置 /Result/ 过滤两阶段聚合（类似 MapReduce）每个 awk 进程独立处理 4 个文件性能：处理时间：18 秒速度提升：174 倍（相比 Hadoop）5. 最终方案：使用 mawk使用 mawk 替代 gawk（性能更优）：find . -type f -name '*.pgn' -print0 | \ xargs -0 -n4 -P4 mawk '/Result/ { split($0, a, "-"); res = substr(a[1], length(a[1]), 1); if (res == 1) white++; if (res == 0) black++; if (res == 2) draw++ } END { print white+black+draw, white, black, draw }' | \ mawk '{ games += $1; white += $2; black += $3; draw += $4; } END { print games, white, black, draw }'性能：处理时间：12 秒处理速度：270MB/秒速度提升：235 倍（相比 Hadoop）五、架构对比1. Hadoop MapReduce 架构graph TB Input[输入文件] --> Split[输入分片] Split --> Map1[Map 任务 1] Split --> Map2[Map 任务 2] Split --> Map3[Map 任务 N] Map1 --> Shuffle[Shuffle 排序] Map2 --> Shuffle Map3 --> Shuffle Shuffle --> Reduce1[Reduce 任务] Shuffle --> Reduce2[Reduce 任务] Reduce1 --> Output[输出结果] Reduce2 --> Output style Input fill:#e1f5ff style Output fill:#e1f5ff style Map1 fill:#fff4e1 style Map2 fill:#fff4e1 style Map3 fill:#fff4e1 style Reduce1 fill:#ffe1f5 style Reduce2 fill:#ffe1f5组件说明：Map 阶段：解析和提取Shuffle 阶段：数据分发和排序Reduce 阶段：聚合统计HDFS：分布式存储开销来源：任务调度和启动JVM 进程开销网络数据传输磁盘 I/O（中间结果）2. Unix 管道架构graph LR Input[输入文件] --> Find[find] Find --> Xargs[xargs 并行] Xargs --> Awk1[mawk 进程 1] Xargs --> Awk2[mawk 进程 2] Xargs --> Awk3[mawk 进程 3] Xargs --> Awk4[mawk 进程 4] Awk1 --> Aggregator[mawk 聚合] Awk2 --> Aggregator Awk3 --> Aggregator Awk4 --> Aggregator Aggregator --> Output[输出结果] style Input fill:#e1f5ff style Output fill:#e1f5ff style Awk1 fill:#e8f5e9 style Awk2 fill:#e8f5e9 style Awk3 fill:#e8f5e9 style Awk4 fill:#e8f5e9 style Aggregator fill:#fff3e0组件说明：find：文件查找xargs：并行执行控制mawk：流式数据处理管道：进程间通信优势：无需调度框架原生代码执行零拷贝管道通信流式处理，内存占用极低六、性能分析1. 处理速度对比表方案数据量处理时间速度相对 Hadoop 倍数Hadoop 集群1.75GB26 分钟1.14MB/秒1×初版管道3.46GB70 秒50MB/秒44×awk 优化3.46GB65 秒54MB/秒47×并行 grep3.46GB38 秒92MB/秒77×纯 awk3.46GB18 秒195MB/秒174×mawk 最终版3.46GB12 秒270MB/秒235×2. 性能优化路径graph LR A[Hadoop 26分钟] --> B[初版管道 70秒] B --> C[awk优化 65秒] C --> D[并行grep 38秒] D --> E[纯awk 18秒] E --> F[mawk最终版 12秒] style A fill:#ffcdd2 style B fill:#fff9c4 style C fill:#fff9c4 style D fill:#c8e6c9 style E fill:#a5d6a7 style F fill:#81c7843. 优化要点总结流式处理：逐行处理，无需全量加载内存占用恒定（仅存储计数器）并行化：xargs -P4：4 个进程并行每个进程独立处理文件工具选择：mawk vs gawk：性能提升约 50%移除 grep：减少进程启动开销批处理优化：-n4：每个进程处理 4 个文件减少进程启动次数七、内存使用对比1. Hadoop 方案内存占用：每个 Mapper/Reducer：JVM 堆内存数据缓存：Shuffle 阶段框架开销：Hadoop 自身内存需求Tom Hayden 的体验：加载 10000 局棋谱到内存内存不足报警2. 命令行方案内存占用：mawk 进程：仅存储 4 个计数器（总场次、白胜、黑胜、和棋）管道缓冲：少量内核缓冲区总占用：几乎可以忽略优势：数据规模无关性可处理远超内存容量的数据八、适用场景分析1. Hadoop 适用场景推荐使用：数据量：TB 级别以上复杂分析：多阶段 MapReduce实时需求：低，批处理为主团队：有专门的运维团队硬件：已有集群资源典型应用：日志分析（海量）机器学习训练复杂 ETL 流程图计算2. 命令行工具适用场景推荐使用：数据量：GB 级别简单分析：过滤、聚合、统计实时需求：高，快速迭代团队：个人或小团队硬件：单机即可典型应用：日志快速分析数据探索临时统计任务数据预处理3. 决策树graph TD A[数据分析任务] --> B{数据量} B -->|< 100GB| C{任务复杂度} B -->|> 10TB| D[Hadoop/Spark] B -->|100GB-10TB| E{团队资源} C -->|简单聚合| F[命令行工具] C -->|复杂多阶段| D E -->|有集群| G{复杂度} E -->|无集群| F G -->|高| D G -->|低| H[数据库/SQL] style F fill:#a5d6a7 style D fill:#90caf9 style H fill:#fff59d九、核心启示1. 工具选择原则不要过度工程化：不是所有数据问题都需要 Big Data 工具简单工具足够时，避免引入复杂框架理解问题本质：Tom 的任务本质是流式聚合批量加载到内存是错误思路性能与复杂度权衡：Hadoop 开发成本高命令行工具即写即用2. Unix 哲学的胜利小而美：每个工具专注一件事组合起来完成复杂任务文本流：通用接口标准无缝协作并行能力：管道天然支持并行充分利用多核 CPU3. 现代反思Big Data 炒作：很多场景不需要分布式框架性能、成本、维护成本都要考虑传统工具的价值：Unix 工具历经几十年考验性能和稳定性都经过验证工程实践建议：先用简单工具验证可行性确实需要时再上复杂方案定期评估技术栈合理性十、总结1. 性能对比指标Hadoop 集群命令行工具优势处理时间26 分钟12 秒命令行 130×处理速度1.14MB/秒270MB/秒命令行 237×硬件需求7 台服务器1 台笔记本命令行 成本低内存占用高几乎为零命令行 更优开发时间较长即写即用命令行 更快2. 关键结论对于这个具体案例：235 倍性能提升：命令行工具完胜成本优势：无需集群，单机即可开发效率：几行命令 vs 完整 MapReduce 程序3. 适用性判断命令行工具适合：数据量在 GB 级别分析逻辑简单需要快速迭代资源有限Hadoop/Spark 适合：数据量在 TB 级别以上复杂多阶段分析已有集群资源需要容错和高可用4. 最终建议在选择技术方案时：先评估数据规模：不要为了使用工具而使用考虑总拥有成本：开发、部署、维护都要算从简单开始：先用简单工具，验证后再优化保持技术敏锐：了解各种工具的适用边界正如 Adam Drake 所说：如果你确实有海量数据或真正需要分布式处理，那么 Hadoop 这样的工具可能是必需的。但如今我经常看到 Hadoop 被用在传统关系型数据库或其他解决方案在性能、实现成本和持续维护方面都会更好的地方。参考资料Command-line Tools can be 235x Faster than your Hadoop Cluster
Jenkins 环境变量加载问题根因分析与解决方案
Jenkins 环境变量加载问题根因分析与解决方案一、事件概述1. 事件背景在 Jenkins CI/CD 流水线中使用 Claude Code CLI 时，遇到 API Key 认证失败的问题。尽管在 ~/.bashrc 文件中正确配置了 ANTHROPIC 相关环境变量，但 Jenkins 任务仍然报错 Invalid API key。2. 影响范围A. 影响范围所有依赖 Claude Code CLI 的 Jenkins 自动化任务B. 影响功能文档自动生成流水线博客自动发布流程依赖 Claude API 的自动化脚本3. 严重程度P2 级问题（影响自动化流水线，但有临时解决方案）二、事件时间线1. 问题发现A. 现象描述Jenkins 构建任务执行失败，错误信息：Invalid API key · Please run /loginB. 故障环境Jenkins Master：192.168.124.86Jenkins Agent：mlab.dev.vm1（lab 用户）执行命令：claude -p /chinese-doc-generator ...2. 问题排查A. 本地验证SSH 登录到 Jenkins Agent 手动执行命令，一切正常。B. 对比分析本地交互式 Shell 可以加载环境变量，Jenkins 非交互式 Shell 无法加载。3. 根因定位检查 ~/.bashrc 文件开头发现：# ~/.bashrc: executed by bash(1) for non-login shells. # If not running interactively, don't do anything case $- in *i*) ;; *) return;; esac这一段代码导致非交互式 Shell 直接返回，跳过了后续所有环境变量定义。三、问题分析1. 直接原因~/.bashrc 在文件开头有明确的非交互式 Shell 检查，导致 Jenkins 使用的非交互式 Shell 无法加载环境变量。2. Shell 配置文件加载机制graph TD A[Shell 启动] --> B{Shell 类型} B -->|Login Shell| C[加载 /etc/profile] C --> D[加载 ~/.profile] D --> E[加载 ~/.bashrc] B -->|非登录交互式| F[加载 /etc/bash.bashrc] F --> E B -->|非交互式| G[不自动加载任何配置] G --> H[除非显式 source] E --> I{是否交互式} I -->|是| J[执行后续配置] I -->|否| K[立即返回] K --> L[环境变量未加载]3. 根本原因（5 Whys 分析）A. 为什么环境变量没有生效？因为 ~/.bashrc 在非交互式模式下直接 return 了。B. 为什么 ~/.bashrc 会直接返回？这是 Ubuntu 默认 bashrc 配置的保护机制，避免非交互式 Shell 加载不必要的配置。C. 为什么本地正常而 Jenkins 不正常？本地 SSH 登录是 Login Shell，会加载 ~/.profile；Jenkins 使用非交互式 Shell，且没有显式 source bashrc。D. 为什么在 Jenkins 脚本中直接设置有效？因为在当前 Shell 进程中直接 export 环境变量，不依赖配置文件加载机制。E. 深层问题是什么？对 Linux Shell 配置文件加载机制理解不足，没有针对 CI/CD 环境正确配置环境变量。四、解决方案1. 方案对比方案优点缺点推荐度移至 ~/.profile标准 Linux 做法，所有 Shell 都能加载需要 SSH 重新登录生效⭐⭐⭐⭐⭐Jenkins 脚本显式 source灵活，不影响其他环境每个 Job 都要配置⭐⭐⭐创建独立 .env 文件配置清晰，易于管理需要修改 Jenkins 配置⭐⭐⭐⭐Jenkins 全局环境变量集中管理，对所有 Job 生效需要 Jenkins UI 操作⭐⭐⭐⭐修改 bashrc 结构一劳永逸可能影响其他非交互式场景⭐⭐2. 推荐方案：环境变量分层配置A. 核心思路不同类型的配置放到不同的配置文件中，遵循 Linux 标准实践。B. 具体实施将 API Key 等敏感环境变量移至 ~/.profile：# ~/.profile - 适用于 Login Shell 和非交互式 Shell export ANTHROPIC_BASE_URL=https://open.bigmodel.cn/api/anthropic export ANTHROPIC_AUTH_TOKEN=your_api_key_here export ANTHROPIC_API_KEY=your_api_key_here在 ~/.bashrc 中保留交互式 Shell 特定配置：# ~/.bashrc - 适用于交互式 Shell # 别名、函数、提示符等 alias ll='ls -alF' alias la='ls -A' alias l='ls -CF'C. 配置文件加载顺序graph LR A[Shell 启动] --> B{Login Shell} B -->|是| C[~/.profile] B -->|否| D[~/.bashrc] C --> E{调用 bashrc} E -->|是| D D --> F{交互式检查} F -->|通过| G[加载交互式配置] F -->|失败| H[返回] C --> I[环境变量已加载]3. Jenkins 配置最佳实践A. 方式一：使用环境变量文件pipeline { agent { label 'mlab.dev.vm1' } stages { stage('Build') { steps { sh ''' source ~/.profile cd /mydata/code/write/news/ claude -p /chinese-doc-generator "${content}" ''' } } } }B. 方式二：使用 Jenkins Credentialspipeline { agent { label 'mlab.dev.vm1' } environment { ANTHROPIC_API_KEY = credentials('claude-api-key') } stages { stage('Build') { steps { sh 'claude -p /chinese-doc-generator "${content}"' } } } }C. 方式三：使用全局工具配置在 Jenkins 系统配置中添加环境变量，对所有 Job 生效。五、经验总结1. 核心知识点Login Shell：加载顺序为 /etc/profile → ~/.profile → ~/.bashrc非登录交互式 Shell：加载 /etc/bash.bashrc → ~/.bashrc非交互式 Shell：默认不加载任何配置文件，除非显式 source~/.bashrc：通常包含交互式检查，非交互式会提前返回2. CI/CD 环境配置原则环境变量应放在 ~/.profile 或 /etc/environment 中不要在 ~/.bashrc 中放置 CI/CD 需要的环境变量使用 Jenkins Credentials 管理敏感信息优先使用 Jenkins 原生配置而非依赖 Shell 配置文件3. 排查技巧使用 echo $- 检查 Shell 是否为交互式（包含 i 表示交互式）使用 shopt login_shell 检查是否为 Login Shell在 Jenkins 脚本中添加 set -x 查看执行过程使用 env | grep ANTHROPIC 验证环境变量是否加载4. 预防措施在部署新的 CI/CD 任务前，先在 Agent 上模拟非交互式执行建立环境变量配置规范文档使用 Infrastructure as Code 工具（如 Ansible）统一管理配置参考资料Bash Manual - Bash Startup FilesJenkins Pipeline Environment Variables