mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 22:34:02 +01:00
Follow-up to9085a4e5, which recorded services_units.sh at 84.51% because its remaining branches sit behind [[ -f /etc/systemd/system/*.service ]] -- absolute root-owned paths that exist on this machine, so the else-branch never runs and no PATH shim can redirect it. All 87 such paths across the seven check libs now go through $SYSROOT, read from SERVICES_ROOT. The prefix is deliberately NOT defaulted. Three commands in hosts_fix_resolved run outside `run` and so are not stopped by --dry-run (chattr -i on resolved.conf.d, find -delete over its *.conf, and an append to resolved.conf); with an empty default, a test that forgot to set SERVICES_ROOT would really delete this machine's resolved.conf drop-ins. Unset is therefore a hard error and only an explicitly empty value means the real filesystem. The harness now owns PATH outright: $FAKE_BIN for shims and staged fake apps, $REAL_BIN for a curated set of symlinks to genuine coreutils. The machine's /usr/bin is deliberately absent -- a really-installed discord and chromium otherwise make the "no target apps present" branches untestable, which is exactly what happened until these tests caught it. Coverage, measured against run_all.sh because two test files jointly cover services_common.sh after the 250-cap split: common 55/55, report 27/27, units 72/72 (was 84.51%), wrappers 100/100, apps 66/66, browser 79/79 -- seven libs at 100%. services_hosts.sh reads 86.05% and services_hosts_fix.sh 97.30%, and those 14 lines are a kcov attribution artifact rather than a gap. Falsified rather than assumed: the suite prints "51 passed, 0 failed" when run under kcov, so no group is skipped, and every supposedly-uncovered line is an issues+=("...") whose string can only reach stdout through the print loop below it -- with a passing assertion matching that exact string. Two falsification checks, both re-run after the rewrite: `--status --dry-run` as root stays byte-identical to rev6691cb26modulo the Date: line, and the sha256sums of /etc/hosts, /etc/nsswitch.conf and /etc/systemd/resolved.conf plus the contents of resolved.conf.d are unchanged across a full suite run. The second one is what makes a missed prefix site detectable instead of a matter of inspection: the repair paths really do write. 220 assertions across 8 test files. Also fixes a bug in the harness's own lsattr shim, where printf with a leading-dash format string parsed the dashes as options and silently produced nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F3PzGc75gBcdxP3PkHXGcV
192 lines
7.4 KiB
Bash
Executable File
192 lines
7.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# Script to check and enable all digital wellbeing services
|
|
# Checks: pacman wrapper, midnight shutdown, startup monitor, periodic systems, hosts and hosts guard
|
|
#
|
|
# Usage:
|
|
# sudo ./check_and_enable_services.sh [options]
|
|
# Options:
|
|
# --dry-run Show what would be done without making changes
|
|
# --status Only show status, don't enable anything
|
|
# -h|--help Show help
|
|
|
|
set -euo pipefail
|
|
|
|
# Prefix for every absolute path the checks probe. Empty means the real
|
|
# filesystem, which is the only value production ever uses; the test harness
|
|
# points it at a fixture tree instead. The libs read it via `${SERVICES_ROOT?}`
|
|
# with no default, so this assignment is required rather than optional: several
|
|
# repairs write outside `run` (chattr, find -delete, an append to
|
|
# resolved.conf), and a caller that forgot to set it would edit the real /etc.
|
|
export SERVICES_ROOT=""
|
|
|
|
# Every check lives in a lib beside this file; this script keeps only the
|
|
# configuration, argument parsing and the order the checks run in.
|
|
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib"
|
|
# shellcheck source=lib/services_common.sh
|
|
. "$LIB_DIR/services_common.sh"
|
|
# shellcheck source=lib/services_wrappers.sh
|
|
. "$LIB_DIR/services_wrappers.sh"
|
|
# shellcheck source=lib/services_units.sh
|
|
. "$LIB_DIR/services_units.sh"
|
|
# shellcheck source=lib/services_hosts.sh
|
|
. "$LIB_DIR/services_hosts.sh"
|
|
# shellcheck source=lib/services_hosts_fix.sh
|
|
. "$LIB_DIR/services_hosts_fix.sh"
|
|
# shellcheck source=lib/services_apps.sh
|
|
. "$LIB_DIR/services_apps.sh"
|
|
# shellcheck source=lib/services_browser.sh
|
|
. "$LIB_DIR/services_browser.sh"
|
|
# shellcheck source=lib/services_report.sh
|
|
. "$LIB_DIR/services_report.sh"
|
|
|
|
######################################################################
|
|
# Configuration
|
|
######################################################################
|
|
DRY_RUN=0
|
|
STATUS_ONLY=0
|
|
|
|
# Colors
|
|
RED=$'\033[0;31m'
|
|
GREEN=$'\033[0;32m'
|
|
YELLOW=$'\033[0;33m'
|
|
BLUE=$'\033[0;34m'
|
|
CYAN=$'\033[0;36m'
|
|
NC=$'\033[0m' # No Color
|
|
|
|
# Get script and config directories
|
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
CONFIG_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
|
|
# Script paths
|
|
PACMAN_WRAPPER_INSTALL="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/pacman/install_pacman_wrapper.sh"
|
|
MAKEPKG_WRAPPER_INSTALL="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/pacman/install_makepkg_wrapper.sh"
|
|
# Drift manifests written by the two installers above (see deployment_drift).
|
|
PACMAN_WRAPPER_MANIFEST="/var/lib/pacman-wrapper/source.sha256"
|
|
MAKEPKG_WRAPPER_MANIFEST="/var/lib/pacman-wrapper/makepkg-source.sha256"
|
|
MIDNIGHT_SHUTDOWN_SCRIPT="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/setup_midnight_shutdown.sh"
|
|
STARTUP_MONITOR_SCRIPT="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/setup_pc_startup_monitor.sh"
|
|
PERIODIC_SYSTEM_SCRIPT="$CONFIG_DIR/scripts/periodic_background/setup_periodic_system.sh"
|
|
HOSTS_INSTALL_SCRIPT="$CONFIG_DIR/scripts/periodic_background/hosts/install.sh"
|
|
GUARD_LIB_MIGRATE_SCRIPT="$CONFIG_DIR/scripts/single_use/fixes/migrate_hosts_guard_to_guard_lib.sh"
|
|
COMPULSIVE_BLOCK_SCRIPT="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/block_compulsive_opening.sh"
|
|
LEECHBLOCK_SCRIPT="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/install_leechblock.sh"
|
|
REMOVE_GUEST_MODE_SCRIPT="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/remove_guest_mode.sh"
|
|
VBOX_HOSTS_SCRIPT="$CONFIG_DIR/scripts/periodic_background/digital_wellbeing/virtualbox/enforce_vbox_hosts.sh"
|
|
# screen-locker was EXTRACTED out of this monorepo into its own repo
|
|
# (github.com/kuhyx/screen-locker, checked out at ~/screen-locker), so these
|
|
# paths deliberately live outside testsAndMisc. They used to point at
|
|
# python_pkg/screen_locker/, which stopped existing at extraction time — the
|
|
# result was check_workout_locker reporting a red "error" for a service that was
|
|
# installed and enabled the whole time, while its "fix" silently did nothing.
|
|
# Resolve the invoking user's home: this script re-execs itself via sudo, so
|
|
# $HOME would be /root here.
|
|
REAL_USER="${SUDO_USER:-${USER:-$(id -un)}}"
|
|
REAL_HOME="$(getent passwd "$REAL_USER" 2>/dev/null | cut -d: -f6)"
|
|
[[ -n $REAL_HOME ]] || REAL_HOME="/home/$REAL_USER"
|
|
WORKOUT_LOCKER_REPO="$REAL_HOME/screen-locker"
|
|
WORKOUT_LOCKER_INSTALL_SCRIPT="$WORKOUT_LOCKER_REPO/install_systemd.sh"
|
|
WORKOUT_LOCKER_SCRIPT="$WORKOUT_LOCKER_REPO/screen_locker/screen_lock.py"
|
|
|
|
# A MISSING repair script means THIS TOOL is broken: it silently stops repairing
|
|
# the thing it exists to repair. That is exactly how the 2026-05-15 reorg left a
|
|
# stale $CONFIG_DIR/hosts path here — check_hosts detected the disabled guards
|
|
# every run, failed to find setup_hosts_guard.sh, printed one line among a
|
|
# hundred, and still exited 0. Five months of dead self-repair, zero symptoms.
|
|
# So: record it, log at journal ERROR priority, and exit non-zero with a banner.
|
|
declare -a MISSING_SCRIPTS=()
|
|
|
|
######################################################################
|
|
# Parse arguments
|
|
######################################################################
|
|
ORIGINAL_ARGS=("$@")
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--dry-run)
|
|
DRY_RUN=1
|
|
shift
|
|
;;
|
|
--status)
|
|
STATUS_ONLY=1
|
|
shift
|
|
;;
|
|
-h | --help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
err "Unknown option: $1"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
require_root "${ORIGINAL_ARGS[@]}"
|
|
|
|
######################################################################
|
|
# Status tracking
|
|
######################################################################
|
|
declare -A SERVICE_STATUS
|
|
ISSUES_FOUND=0
|
|
FIXES_APPLIED=0
|
|
|
|
######################################################################
|
|
# Check functions
|
|
######################################################################
|
|
|
|
######################################################################
|
|
# Main
|
|
######################################################################
|
|
main() {
|
|
echo ""
|
|
echo "Digital Wellbeing Services Status Check"
|
|
echo "========================================"
|
|
echo "Date: $(date)"
|
|
echo "User: ${SUDO_USER:-$USER}"
|
|
if [[ $DRY_RUN -eq 1 ]]; then
|
|
echo "Mode: DRY RUN (no changes will be made)"
|
|
elif [[ $STATUS_ONLY -eq 1 ]]; then
|
|
echo "Mode: STATUS ONLY (no changes will be made)"
|
|
else
|
|
echo "Mode: CHECK AND FIX"
|
|
fi
|
|
|
|
check_pacman_wrapper
|
|
check_makepkg_wrapper
|
|
check_midnight_shutdown
|
|
check_startup_monitor
|
|
check_periodic_systems
|
|
check_hosts
|
|
check_compulsive_blocker
|
|
check_leechblock
|
|
check_guest_mode_removal
|
|
check_vbox_hosts
|
|
check_workout_locker
|
|
|
|
print_summary
|
|
}
|
|
|
|
main
|
|
|
|
######################################################################
|
|
# A missing repair script means this tool cannot do the one job it exists for.
|
|
# Exiting 0 there is indistinguishable from "everything is fine" — which is how
|
|
# it hid dead hosts self-repair for five months. Make it impossible to miss.
|
|
######################################################################
|
|
if [[ ${#MISSING_SCRIPTS[@]} -gt 0 ]]; then
|
|
printf '\n%s' "$RED"
|
|
printf '=%.0s' {1..74}
|
|
printf "\n SELF-REPAIR IS BROKEN — %d repair script(s) MISSING\n" "${#MISSING_SCRIPTS[@]}"
|
|
printf '=%.0s' {1..74}
|
|
printf '%s\n' "$NC"
|
|
for missing in "${MISSING_SCRIPTS[@]}"; do
|
|
err "$missing"
|
|
done
|
|
printf '%sThe services above are NOT being repaired — this tool found the\n' "$RED"
|
|
printf 'problem and then could not run the fix. Correct these paths first.%s\n' "$NC"
|
|
printf '%sAlso logged at error priority: journalctl -p err -t check-and-enable-services%s\n\n' "$CYAN" "$NC"
|
|
exit 2
|
|
fi
|
|
|
|
exit 0
|