137 lines
4.3 KiB
Bash
137 lines
4.3 KiB
Bash
cmd=${1:-help}
|
|
ct_name=${2:-}
|
|
|
|
require_name() {
|
|
if [ -z "$ct_name" ]; then
|
|
echo "usage: ct $cmd <container>" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
case "$cmd" in
|
|
list)
|
|
sep() { printf '%0.s-' {1..60}; printf '\n'; }
|
|
uptime_str() {
|
|
awk '{s=int($1);d=int(s/86400);h=int((s%86400)/3600);m=int((s%3600)/60);
|
|
if(d>0)printf "%d days %d hours %d minutes",d,h,m;
|
|
else if(h>0)printf "%d hours %d minutes",h,m;
|
|
else printf "%d minutes",m}' /proc/uptime
|
|
}
|
|
|
|
printf 'HOST: %s UP: %s\n' "$(hostname)" "$(uptime_str)"
|
|
sep
|
|
|
|
printf 'CONTAINERS\n'
|
|
mapfile -t all_units < <({
|
|
systemctl list-unit-files --no-legend --no-pager --plain 2>/dev/null
|
|
systemctl list-units --all --no-legend --no-pager --plain 2>/dev/null
|
|
} | awk '$1 ~ /^container@.+\.service$/ {print $1}' | sort -u)
|
|
|
|
if [ ${#all_units[@]} -gt 0 ]; then
|
|
systemctl show "${all_units[@]}" \
|
|
--property=Id,UnitFileState,ActiveState --no-pager 2>/dev/null \
|
|
| awk '
|
|
/^Id=container@/ { n=$0; sub(/^Id=container@/,"",n); sub(/\.service$/,"",n) }
|
|
/^UnitFileState=/ { f=$0; sub(/^UnitFileState=/,"",f) }
|
|
/^ActiveState=/ { a=$0; sub(/^ActiveState=/,"",a) }
|
|
/^[[:space:]]*$/ { if (n!="") { _print(); n=f=a="" } }
|
|
END { if (n!="") _print() }
|
|
function _print() {
|
|
start = (f=="enabled") ? "auto" : "manual"
|
|
if (a=="active") st="running"
|
|
else if (a=="failed") st="FAILED"
|
|
else if (a=="inactive") st="stopped"
|
|
else st=(a!="") ? a : "not-loaded"
|
|
mid = "-"
|
|
if (a == "active") {
|
|
midcmd = "machinectl show " n " -p Id --value 2>/dev/null"
|
|
got = ""
|
|
midcmd | getline got
|
|
close(midcmd)
|
|
if (got != "") mid = substr(got,1,12) "..."
|
|
}
|
|
printf " %-35s %-8s %-10s %s\n", n, start, st, mid
|
|
}
|
|
'
|
|
else
|
|
printf ' none\n'
|
|
fi
|
|
|
|
sep
|
|
|
|
printf 'FAILED UNITS (host)\n'
|
|
failed=$(systemctl list-units --state=failed --no-legend --no-pager --plain 2>/dev/null \
|
|
| awk 'NF>0{print $1}')
|
|
if [ -z "$failed" ]; then printf ' none\n'
|
|
else printf '%s\n' "$failed" | sed 's/^/ /'; fi
|
|
|
|
sep
|
|
|
|
printf 'FAILED UNITS (containers)\n'
|
|
any_failed=0
|
|
machines=$(machinectl list --no-legend --no-pager 2>/dev/null | awk 'NF>0{print $1}')
|
|
for m in $machines; do
|
|
ct_failed=$(sudo systemctl -M "$m" list-units --state=failed \
|
|
--no-legend --no-pager --plain 2>/dev/null \
|
|
| awk 'NF>0 && $1!~/^container@/{print $1}' || true)
|
|
if [ -n "$ct_failed" ]; then
|
|
printf ' [%s]\n' "$m"
|
|
printf '%s\n' "$ct_failed" | sed 's/^/ /'
|
|
any_failed=1
|
|
fi
|
|
done
|
|
[ "$any_failed" -eq 0 ] && printf ' none\n'
|
|
|
|
sep
|
|
|
|
df -h /persist | awk 'NR==2{printf "DISK %s used / %s total (%s)\n",$3,$2,$5}'
|
|
free -h | awk '/^Mem:/{printf "MEM %s used / %s total\n",$3,$2}'
|
|
;;
|
|
start)
|
|
require_name
|
|
sudo systemctl start "container@$ct_name"
|
|
;;
|
|
stop)
|
|
require_name
|
|
sudo systemctl stop "container@$ct_name"
|
|
;;
|
|
restart)
|
|
require_name
|
|
sudo systemctl restart "container@$ct_name"
|
|
;;
|
|
status)
|
|
require_name
|
|
machinectl status "$ct_name"
|
|
;;
|
|
logs)
|
|
require_name
|
|
shift 2
|
|
sudo journalctl -M "$ct_name" --no-hostname "$@"
|
|
;;
|
|
shell)
|
|
require_name
|
|
exec sudo machinectl shell "$ct_name"
|
|
;;
|
|
attach)
|
|
require_name
|
|
leader=$(machinectl show "$ct_name" -p Leader --value 2>/dev/null)
|
|
if [ -z "$leader" ] || [ "$leader" = "0" ]; then
|
|
printf 'error: container %s is not running\n' "$ct_name" >&2
|
|
exit 1
|
|
fi
|
|
exec sudo nsenter -m -t "$leader" -- dtach -a -r none /run/ct-attach/attach.sock
|
|
;;
|
|
*)
|
|
printf 'usage: ct <cmd> [container]\n\n'
|
|
printf ' %-9s %-13s %s\n' \
|
|
"list" "" "list all containers with state (running/stopped/FAILED)" \
|
|
"start" "<container>" "start a container" \
|
|
"stop" "<container>" "stop a container" \
|
|
"restart" "<container>" "restart a container" \
|
|
"status" "<container>" "show container status" \
|
|
"logs" "<container>" "view logs (extra args forwarded to journalctl)" \
|
|
"shell" "<container>" "open a shell" \
|
|
"attach" "<container>" "attach to Minecraft console (detach: Ctrl+\\)"
|
|
;;
|
|
esac
|