Skip to content

Commit a042bd0

Browse files
authored
Create cleanup_workspace
1 parent ad54d3f commit a042bd0

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

scripts/cleanup_workspace

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# cleanup_workspace.sh
5+
# Unmounts any lingering chroot mounts from interrupted builds and removes
6+
# the workspace directory.
7+
8+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
10+
WORKSPACE_DIR="$REPO_ROOT/workspace"
11+
MAX_UMOUNT_PASSES=5
12+
13+
run_privileged() {
14+
if [[ "$EUID" -eq 0 ]]; then
15+
"$@"
16+
else
17+
sudo "$@"
18+
fi
19+
}
20+
21+
list_workspace_mounts() {
22+
if command -v findmnt >/dev/null 2>&1; then
23+
findmnt -rn -o TARGET | awk -v ws="$WORKSPACE_DIR" '$0 == ws || index($0, ws "/") == 1' | sort -r -u || true
24+
return
25+
fi
26+
27+
# Fallback if findmnt is unavailable.
28+
awk '{print $2}' /proc/mounts \
29+
| sed 's/\\040/ /g' \
30+
| awk -v ws="$WORKSPACE_DIR" '$0 == ws || index($0, ws "/") == 1' \
31+
| sort -r -u || true
32+
}
33+
34+
try_unmount_once() {
35+
local mount_point="$1"
36+
echo " unmounting: $mount_point"
37+
38+
if run_privileged umount "$mount_point" 2>/dev/null; then
39+
return 0
40+
fi
41+
42+
# Busy mounts from interrupted chroots often require lazy unmount.
43+
if run_privileged umount -l "$mount_point" 2>/dev/null; then
44+
echo " used lazy unmount for busy mount"
45+
return 0
46+
fi
47+
48+
return 1
49+
}
50+
51+
usage() {
52+
echo "Usage: $0 [--workspace-dir DIR] [--max-umount-passes N] [-h|--help]"
53+
echo " --workspace-dir DIR Override workspace directory (default: $WORKSPACE_DIR)"
54+
echo " --max-umount-passes N Number of unmount retry passes (default: $MAX_UMOUNT_PASSES)"
55+
echo " -h, --help Show this help message"
56+
}
57+
58+
while [[ $# -gt 0 ]]; do
59+
case $1 in
60+
--workspace-dir)
61+
WORKSPACE_DIR="$2"
62+
shift 2
63+
;;
64+
--max-umount-passes)
65+
MAX_UMOUNT_PASSES="$2"
66+
shift 2
67+
;;
68+
-h|--help)
69+
usage
70+
exit 0
71+
;;
72+
*)
73+
echo "Unknown option: $1"
74+
usage
75+
exit 1
76+
;;
77+
esac
78+
done
79+
80+
if [[ ! -d "$WORKSPACE_DIR" ]]; then
81+
echo "Workspace directory does not exist: $WORKSPACE_DIR"
82+
exit 0
83+
fi
84+
85+
echo "Cleaning up workspace: $WORKSPACE_DIR"
86+
87+
if ! [[ "$MAX_UMOUNT_PASSES" =~ ^[0-9]+$ ]] || [[ "$MAX_UMOUNT_PASSES" -lt 1 ]]; then
88+
echo "Invalid --max-umount-passes value: $MAX_UMOUNT_PASSES"
89+
exit 1
90+
fi
91+
92+
# Find all active mounts under the workspace, sort in reverse order (deepest first)
93+
# so child mounts are unmounted before parents.
94+
MOUNTS="$(list_workspace_mounts)"
95+
96+
if [[ -z "$MOUNTS" ]]; then
97+
echo "No active mounts found under $WORKSPACE_DIR"
98+
else
99+
pass=1
100+
while [[ "$pass" -le "$MAX_UMOUNT_PASSES" ]]; do
101+
MOUNTS="$(list_workspace_mounts)"
102+
if [[ -z "$MOUNTS" ]]; then
103+
break
104+
fi
105+
106+
echo "Unmount pass $pass/$MAX_UMOUNT_PASSES"
107+
echo "$MOUNTS"
108+
109+
while IFS= read -r mount_point; do
110+
[[ -z "$mount_point" ]] && continue
111+
if ! try_unmount_once "$mount_point"; then
112+
echo " WARNING: unable to unmount $mount_point in this pass"
113+
fi
114+
done <<< "$MOUNTS"
115+
116+
pass=$((pass + 1))
117+
sleep 1
118+
done
119+
120+
MOUNTS="$(list_workspace_mounts)"
121+
if [[ -n "$MOUNTS" ]]; then
122+
echo "ERROR: Some mounts are still active under $WORKSPACE_DIR"
123+
echo "$MOUNTS"
124+
echo "Try closing terminals/processes using this chroot and rerun."
125+
exit 1
126+
fi
127+
fi
128+
129+
echo "Removing workspace directory..."
130+
run_privileged rm -rf "$WORKSPACE_DIR"
131+
echo "Done."

0 commit comments

Comments
 (0)