#!/usr/bin/env bash # Kill the match containers this worktree started, and nobody else's. # # `sds clean` kills every sds-* container on the machine, which is why # CLAUDE.md forbids running it while somebody else's benchmark is going. This # is the narrow version: a container is ours when its /work bind mount points # at our own worktree, which is how `sds bench` launches it. Containers # belonging to other worktrees are listed and left alone. # # Usage: # scripts/kill-my-containers.sh # kill ours, report the rest # scripts/kill-my-containers.sh --dry-run # say what would happen # scripts/kill-my-containers.sh --worktree DIR set -euo pipefail dry_run=0 worktree="" while [ $# -gt 0 ]; do case "$1" in --dry-run) dry_run=1; shift ;; --worktree) worktree="${2:-}"; shift 2 ;; -h | --help) sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; *) echo "unknown argument: $1" >&2; exit 2 ;; esac done if ! command -v docker > /dev/null 2>&1; then echo "docker not found" >&2 exit 1 fi if [ -z "$worktree" ]; then worktree=$(git rev-parse --show-toplevel) fi # Resolve symlinks so the comparison against docker's own path is exact. worktree=$(cd "$worktree" && pwd -P) echo "ours: $worktree" mine=() theirs=() while IFS= read -r name; do [ -n "$name" ] || continue source_dir=$( docker inspect "$name" \ --format '{{range .Mounts}}{{if eq .Destination "/work"}}{{.Source}}{{end}}{{end}}' \ 2> /dev/null || true ) if [ -z "$source_dir" ]; then # No /work mount is not something we can attribute, so we do not touch it. theirs+=("$name (no /work mount)") elif [ "$source_dir" = "$worktree" ]; then mine+=("$name") else theirs+=("$name <- $source_dir") fi done < <(docker ps --format '{{.Names}}' --filter name=sds- 2> /dev/null || true) if [ ${#theirs[@]} -gt 0 ]; then echo echo "leaving ${#theirs[@]} container(s) that are not ours:" for entry in "${theirs[@]}"; do echo " $entry" done fi if [ ${#mine[@]} -eq 0 ]; then echo echo "nothing of ours is running" exit 0 fi echo if [ "$dry_run" -eq 1 ]; then echo "would kill ${#mine[@]} container(s):" for name in "${mine[@]}"; do echo " $name" done exit 0 fi echo "killing ${#mine[@]} container(s):" for name in "${mine[@]}"; do if docker kill "$name" > /dev/null 2>&1; then echo " $name" else # A container that exited between the listing and the kill is not a failure. echo " $name (already gone)" fi done