banger/kill.sh

91 lines
1.8 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
log() {
printf '[kill] %s\n' "$*"
}
usage() {
cat <<'EOF'
Usage: ./kill.sh <id-or-name-prefix> [--signal SIGTERM|SIGKILL|...]
Sends a signal to the Firecracker process.
EOF
}
find_vm_json() {
local query="$1"
local vm_json match_count=0 match=""
for vm_json in state/vms/*/vm.json; do
[[ -f "$vm_json" ]] || continue
local id name
id="$(jq -r '.meta.id // empty' "$vm_json")"
name="$(jq -r '.meta.name // empty' "$vm_json")"
if [[ "$id" == "$query"* || "$name" == "$query"* ]]; then
match="$vm_json"
match_count=$((match_count + 1))
fi
done
if (( match_count == 0 )); then
log "no VM found for prefix: $query"
exit 1
fi
if (( match_count > 1 )); then
log "multiple VMs found for prefix: $query"
exit 1
fi
printf '%s' "$match"
}
SIGNAL="TERM"
while [[ $# -gt 0 ]]; do
case "$1" in
--signal)
SIGNAL="${2:-}"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
if [[ -z "${QUERY:-}" ]]; then
QUERY="$1"
shift
continue
fi
log "unknown option: $1"
usage
exit 1
;;
esac
done
if [[ -z "$QUERY" || "$QUERY" == "-h" || "$QUERY" == "--help" ]]; then
usage
exit 1
fi
VM_JSON="$(find_vm_json "$QUERY")"
PID="$(jq -r '.meta.pid // empty' "$VM_JSON")"
API_SOCK="$(jq -r '.meta.api_sock // empty' "$VM_JSON")"
if [[ -z "$PID" ]]; then
log "pid not found in $VM_JSON"
exit 1
fi
if [[ -z "$API_SOCK" ]]; then
log "api_sock not found in $VM_JSON"
exit 1
fi
if ! ps -p "$PID" -o comm=,args= 2>/dev/null | rg -q "firecracker.*--api-sock $API_SOCK"; then
log "pid $PID does not match a running VM"
exit 1
fi
log "sending SIG$SIGNAL to pid $PID"
sudo kill "-$SIGNAL" "$PID"
log "signal sent"