skills/shell-scripting/SKILL.md
Shell脚本开发技能 - Bash/Zsh脚本、自动化部署、系统管理、文本处理。当你涉及Shell/Bash/Zsh脚本编写、deploy.sh/build.sh等自动化脚本、cron定时任务、系统管理命令、sed/awk/grep文本处理时必须使用此技能。即使用户只是说"写个脚本"或"改下部署脚本",也应触发。
npx skillsauth add 0X6C7879/aegissec shell-scriptingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
[Shell核心清单] ① 脚本首行
#!/usr/bin/env bash+set -euo pipefail② 变量必须"$var"双引号包裹防止分词 ③ 路径用"$(cd "$(dirname "$0")" && pwd)"获取脚本所在目录 [安全三禁] ❌eval "$user_input"❌无引号变量展开 ❌rm -rf /或rm -rf $VAR/(VAR可能为空) [健壮性铁律] 命令失败必须有处理(set -e或显式检查$?),临时文件用mktemp+trap清理
写/改Shell脚本时,强制遵守:
#!/usr/bin/env bash + set -euo pipefail(-e:命令失败即退出 -u:未定义变量报错 -o pipefail:管道中任一命令失败即失败)"$var",防止空格/通配符导致分词。路径变量尤其重要|| { echo "失败"; exit 1; }mktemp创建 + trap 'rm -f "$tmpfile"' EXIT清理,禁止硬编码/tmp/xxxlog() { echo "[$(date '+%H:%M:%S')] $*"; },错误输出到stderrcommand -v检查依赖是否存在#!/usr/bin/env bash
set -euo pipefail
# 脚本所在目录(解析符号链接)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# 日志函数
log() { echo "[$(date '+%H:%M:%S')] $*"; }
err() { echo "[$(date '+%H:%M:%S')] ERROR: $*" >&2; }
die() { err "$@"; exit 1; }
# 依赖检查
for cmd in go rsync ssh; do
command -v "$cmd" >/dev/null 2>&1 || die "缺少依赖: $cmd"
done
# 清理函数
cleanup() {
# 清理临时文件等
:
}
trap cleanup EXIT
# 主逻辑
main() {
log "开始执行..."
# ...
log "完成"
}
main "$@"
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REMOTE_HOST="user@server"
REMOTE_DIR="/path/to/deploy"
SERVICE_NAME="myservice"
log() { echo "[$(date '+%H:%M:%S')] $*"; }
die() { echo "[$(date '+%H:%M:%S')] ERROR: $*" >&2; exit 1; }
# 构建
log "构建中..."
cd "$SCRIPT_DIR"
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o "build/${SERVICE_NAME}" . || die "构建失败"
# 上传
log "上传到 $REMOTE_HOST..."
rsync -az "build/${SERVICE_NAME}" "$REMOTE_HOST:$REMOTE_DIR/" || die "上传失败"
# 重启
log "重启服务..."
ssh "$REMOTE_HOST" "sudo systemctl restart $SERVICE_NAME" || die "重启失败"
# 验证
log "等待服务启动..."
sleep 2
ssh "$REMOTE_HOST" "systemctl is-active $SERVICE_NAME" || die "服务未正常启动"
log "部署完成 ✓"
# 简单参数
while [[ $# -gt 0 ]]; do
case "$1" in
-p|--port) PORT="$2"; shift 2 ;;
-d|--debug) DEBUG=1; shift ;;
-h|--help) usage; exit 0 ;;
*) die "未知参数: $1" ;;
esac
done
# 文件/目录检查
[[ -f "$file" ]] || die "文件不存在: $file"
[[ -d "$dir" ]] || mkdir -p "$dir"
[[ -w "$dir" ]] || die "目录不可写: $dir"
[[ -x "$script" ]] || chmod +x "$script"
# 字符串检查
[[ -n "$var" ]] || die "变量为空: var"
[[ "$var" == "yes" ]] && echo "是"
# 数字比较
(( count > 0 )) || die "count必须大于0"
# SSH执行远程命令
ssh "$host" "cd $dir && ./deploy.sh" || die "远程执行失败"
# SCP/rsync上传
rsync -az --delete "dist/" "$host:$remote_dir/" || die "同步失败"
# 远程检查服务状态
ssh "$host" "systemctl is-active $service" && log "服务运行中" || die "服务未运行"
# grep提取
grep -oP '(?<=version=)[0-9.]+' config.txt
# sed替换(原地修改加-i)
sed -i '' "s/PORT=.*/PORT=$new_port/" .env # macOS
sed -i "s/PORT=.*/PORT=$new_port/" .env # Linux
# awk提取列
awk -F: '{print $1, $3}' /etc/passwd
# 读取文件逐行处理
while IFS= read -r line; do
echo "处理: $line"
done < "$input_file"
# Go交叉编译全平台
platforms=("linux/amd64" "linux/arm64" "darwin/amd64" "darwin/arm64")
for platform in "${platforms[@]}"; do
IFS='/' read -r os arch <<< "$platform"
output="build/${name}_${os}_${arch}"
CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" go build -ldflags="-s -w" -o "$output" .
done
| 规则 | 正确 | 错误 | 原因 |
|------|------|------|------|
| 变量引号 | "$var" | $var | 空格/通配符导致分词 |
| 命令替换 | "$(cmd)" | `cmd` | 反引号嵌套困难 |
| 路径拼接 | "${dir}/${file}" | $dir/$file | dir为空时变成/file(根目录) |
| 删除安全 | rm -rf "${dir:?}/" | rm -rf $dir/ | dir为空时删根目录 |
| 条件判断 | [[ ]] | [ ] | [[支持正则、不分词 |
| 临时文件 | mktemp | /tmp/myapp.tmp | 硬编码有竞争条件+安全风险 |
| 读取输入 | read -r | read | 无-r会处理反斜杠转义 |
# 显示执行的每条命令
set -x # 开启
set +x # 关闭
# 只打印不执行(dry run)
DRY_RUN=${DRY_RUN:-0}
run() {
if (( DRY_RUN )); then
log "[DRY RUN] $*"
else
"$@"
fi
}
# 执行耗时统计
time_start=$(date +%s)
# ... 操作 ...
time_end=$(date +%s)
log "耗时: $((time_end - time_start))秒"
shellcheck检查(如可用)development
WooYun-derived business-logic testing methodology for web apps and APIs. Use when the request involves 支付、退款、订单、越权、认证、授权、价格篡改或业务流程绕过 review, especially black-box probing for price tampering, account takeover, and process bypass flaws.
tools
Escalate privileges on Windows systems using service misconfigurations, DLL hijacking, token manipulation, UAC bypasses, registry exploits, and credential dumping. Use when performing Windows post-exploitation or privilege escalation.
development
Use when performing AD pentest tunneling and pivoting, especially with Ligolo-ng, Chisel, frp, proxychains, SSH forwarding, SOCKS relays, reverse tunnels, or when internal reachability is the main blocker.
development
Threat model, security audit, find vulnerabilities, check security of my app, risk assessment, penetration test prep, analyze attack surface, what could an attacker exploit. Use this skill whenever a user wants holistic security analysis of a codebase, application, or project. MUST be invoked instead of analyzing security yourself — it runs a specialized 8-phase STRIDE workflow producing professional deliverables you cannot generate alone: risk assessment reports, DFD diagrams, threat inventories, attack path validation, mitigation plans, and pentest plans. Trigger on: 威胁建模, 安全评估, 渗透测试, 安全分析, 安全审计, 安全检查, 风险评估. NOT for: fixing one specific bug, adding one security feature (rate limiting, CORS), writing tests, CI/CD setup, or debugging errors.