Until now ./install.sh only managed an already-installed kiosk; ubuntu-based-kiosk.sh was still the only path from a bare Ubuntu Server box to a running one. install.sh now provisions from scratch too: packages, kiosk user, Node.js/Electron, LightDM+Openbox autologin, audio/video/HDMI/power-button hardware setup, and the firewall, then hands off to the already-migrated Core Settings/Advanced menus for initial configuration instead of reimplementing that logic again. - lib/provision.sh: the new provisioning flow, built mostly by calling existing menus (core_settings_menu, emergency hotspot, virtual consoles) - cuts it to ~300 lines against the legacy script's ~4,000-line first_time_install(). - lib/electron.sh: electron_install_binary() extracted out of menus/advanced_electron.sh so provisioning and the existing "Fix blank screen" action share one implementation. - kiosk-app/ and provision/files/: the Electron app source and every system template file, extracted byte-for-byte out of ubuntu-based-kiosk.sh's heredocs into real files. - Found and fixed a bash set -e gotcha along the way: testing a multi-statement function as an if-condition (`if ! some_func; then`) silently exempts everything inside that function from set -e for the duration of the call. Fixed in the new provisioning code and in menus/advanced_electron.sh's pre-existing repair action, which had the same shape. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VfsFSoRqfbRG7XAg5RoE7e
242 lines
9.2 KiB
Bash
242 lines
9.2 KiB
Bash
#!/bin/bash
|
|
################################################################################
|
|
# menus/advanced_electron.sh - "Electron Maintenance" (Advanced): the
|
|
# legacy "Manual Electron Update" and "Fix Blank Screen" items, combined
|
|
# under one submenu since both maintain the same Electron installation.
|
|
# The binary-repair logic itself (electron_install_binary) now lives in
|
|
# lib/electron.sh, shared with fresh provisioning (lib/provision.sh) -
|
|
# the same repair sequence applies whether the binary never downloaded
|
|
# during the initial `npm install` or went missing later.
|
|
#
|
|
# Real system state: $KIOSK_DIR/node_modules, package.json, lightdm.
|
|
# Every write goes through `sudo`/`sudo -u "$KIOSK_USER"`, stubbed at the
|
|
# command level in tests - there's no relocatable equivalent for another
|
|
# project's (npm/Electron's) own directory layout.
|
|
#
|
|
# Depends on: lib/menu.sh, lib/config.sh, lib/electron.sh being sourced first.
|
|
################################################################################
|
|
|
|
electron_installed_version() {
|
|
local package_json="$KIOSK_DIR/package.json"
|
|
if ! sudo test -f "$package_json" 2>/dev/null; then
|
|
echo "not installed"
|
|
return
|
|
fi
|
|
|
|
local version
|
|
version=$(sudo grep -oP '"electron"\s*:\s*"\^?\K[0-9.]+' "$package_json" 2>/dev/null || true)
|
|
if [[ -z "$version" ]]; then
|
|
local electron_pkg="$KIOSK_DIR/node_modules/electron/package.json"
|
|
if sudo test -f "$electron_pkg" 2>/dev/null; then
|
|
version=$(sudo grep -oP '"version"\s*:\s*"\K[0-9.]+' "$electron_pkg" 2>/dev/null || true)
|
|
fi
|
|
fi
|
|
echo "${version:-unknown}"
|
|
}
|
|
|
|
electron_is_running() {
|
|
pgrep -f "electron.*main.js" &>/dev/null || pgrep -f "node.*electron" &>/dev/null
|
|
}
|
|
|
|
advanced_electron_status() {
|
|
local ver
|
|
ver=$(electron_installed_version)
|
|
echo "Electron: v${ver}"
|
|
if electron_is_running; then
|
|
echo " Running"
|
|
else
|
|
echo " Not running"
|
|
fi
|
|
}
|
|
|
|
advanced_electron_menu_builder() {
|
|
MENU_LABELS=(
|
|
"Check for updates / update Electron"
|
|
"Fix blank screen (repair Electron binary + sandbox)"
|
|
)
|
|
MENU_HANDLERS=(action_update_electron action_repair_electron)
|
|
}
|
|
|
|
advanced_electron_menu() {
|
|
run_menu "ELECTRON MAINTENANCE" advanced_electron_menu_builder advanced_electron_status
|
|
}
|
|
|
|
################################################################################
|
|
# Actions
|
|
################################################################################
|
|
|
|
action_update_electron() {
|
|
echo
|
|
if ! sudo test -d "$KIOSK_DIR" 2>/dev/null; then
|
|
log_error "Kiosk directory not found: $KIOSK_DIR"
|
|
pause
|
|
return 1
|
|
fi
|
|
|
|
local current_version
|
|
current_version=$(electron_installed_version)
|
|
log_info "Current Electron version: $current_version"
|
|
|
|
if electron_is_running; then
|
|
log_success "Electron app is running"
|
|
else
|
|
log_warning "Electron app does not appear to be running"
|
|
fi
|
|
echo
|
|
|
|
ask_yes_no "Check for latest Electron version?" "y" || { echo "Cancelled"; pause; return; }
|
|
|
|
local latest_version
|
|
latest_version=$(npm view electron version 2>/dev/null || true)
|
|
if [[ -z "$latest_version" ]]; then
|
|
latest_version=$(curl -s https://registry.npmjs.org/electron/latest 2>/dev/null | grep -oP '"version"\s*:\s*"\K[0-9.]+' || true)
|
|
fi
|
|
if [[ -z "$latest_version" ]]; then
|
|
latest_version=$(curl -s https://api.github.com/repos/electron/electron/releases/latest 2>/dev/null | grep -oP '"tag_name"\s*:\s*"v\K[0-9.]+' || true)
|
|
fi
|
|
|
|
if [[ -z "$latest_version" ]]; then
|
|
log_error "Could not fetch latest Electron version - check your internet connection"
|
|
pause
|
|
return 1
|
|
fi
|
|
log_success "Latest stable Electron version: $latest_version"
|
|
echo
|
|
|
|
if [[ "$current_version" == "$latest_version" ]]; then
|
|
log_success "Already running the latest version"
|
|
ask_yes_no "Reinstall Electron $latest_version anyway?" "n" || { echo "Cancelled"; pause; return; }
|
|
fi
|
|
|
|
echo "──────────────────────────────────────────────────────────"
|
|
echo "UPDATE SUMMARY"
|
|
echo "──────────────────────────────────────────────────────────"
|
|
echo "Current version: $current_version"
|
|
echo "Target version: $latest_version"
|
|
echo "Installation: $KIOSK_DIR"
|
|
echo
|
|
|
|
local current_major="${current_version%%.*}"
|
|
local latest_major="${latest_version%%.*}"
|
|
log_warning "Review breaking changes before updating:"
|
|
echo " https://www.electronjs.org/docs/latest/breaking-changes"
|
|
if [[ "$latest_major" != "$current_major" ]]; then
|
|
log_warning "MAJOR VERSION CHANGE (v${current_major} -> v${latest_major})"
|
|
fi
|
|
echo
|
|
|
|
ask_yes_no "Reviewed breaking changes and want to proceed?" "n" || { echo "Cancelled"; pause; return; }
|
|
|
|
echo
|
|
log_info "Creating backup..."
|
|
local kiosk_owner
|
|
kiosk_owner=$(sudo stat -c '%U' "$KIOSK_DIR" 2>/dev/null || echo "$KIOSK_USER")
|
|
local backup_dir="${KIOSK_DIR}/backups/electron_backup_$(date +%Y%m%d_%H%M%S)"
|
|
sudo -u "$kiosk_owner" mkdir -p "$backup_dir"
|
|
|
|
if sudo test -f "$KIOSK_DIR/package.json" 2>/dev/null; then
|
|
sudo -u "$kiosk_owner" cp "$KIOSK_DIR/package.json" "$backup_dir/"
|
|
fi
|
|
if sudo test -f "$KIOSK_DIR/package-lock.json" 2>/dev/null; then
|
|
sudo -u "$kiosk_owner" cp "$KIOSK_DIR/package-lock.json" "$backup_dir/"
|
|
fi
|
|
echo "$current_version" | sudo -u "$kiosk_owner" tee "$backup_dir/electron_version.txt" > /dev/null
|
|
log_success "Backup created at: $backup_dir"
|
|
echo
|
|
|
|
ask_yes_no "Proceed with Electron update to $latest_version?" "n" || {
|
|
log_info "Update cancelled - backup preserved at: $backup_dir"
|
|
pause
|
|
return
|
|
}
|
|
|
|
echo
|
|
log_info "Stopping kiosk display..."
|
|
sudo systemctl stop lightdm 2>/dev/null || true
|
|
sleep 2
|
|
|
|
sudo -u "$KIOSK_USER" sed -i "s/\"electron\": \".*\"/\"electron\": \"^${latest_version}\"/" "$KIOSK_DIR/package.json"
|
|
|
|
if sudo test -d "$KIOSK_DIR/node_modules/electron" 2>/dev/null; then
|
|
sudo -u "$KIOSK_USER" rm -rf "$KIOSK_DIR/node_modules/electron"
|
|
fi
|
|
|
|
log_info "Installing Electron $latest_version (this may take a few minutes)..."
|
|
if sudo -u "$KIOSK_USER" bash -c "cd '$KIOSK_DIR' && npm install electron@'$latest_version'"; then
|
|
log_success "Electron updated to $latest_version"
|
|
|
|
local sandbox="$KIOSK_DIR/node_modules/electron/dist/chrome-sandbox"
|
|
if sudo test -f "$sandbox" 2>/dev/null; then
|
|
sudo chown root:root "$sandbox"
|
|
sudo chmod 4755 "$sandbox"
|
|
fi
|
|
|
|
if ask_yes_no "Restart kiosk display now?" "y"; then
|
|
sudo systemctl start lightdm
|
|
sleep 3
|
|
if systemctl is-active --quiet lightdm; then
|
|
log_success "Kiosk display started"
|
|
else
|
|
log_error "Kiosk display failed to start - check: sudo journalctl -u lightdm -n 50"
|
|
fi
|
|
else
|
|
log_info "Start manually with: sudo systemctl start lightdm"
|
|
fi
|
|
log_success "Backup preserved at: $backup_dir (delete once confirmed working)"
|
|
else
|
|
log_error "Electron install failed - restoring from backup..."
|
|
if sudo test -f "$backup_dir/package.json" 2>/dev/null; then
|
|
sudo -u "$KIOSK_USER" cp "$backup_dir/package.json" "$KIOSK_DIR/"
|
|
fi
|
|
if sudo -u "$KIOSK_USER" bash -c "cd '$KIOSK_DIR' && npm install"; then
|
|
log_success "Restored original Electron installation"
|
|
sudo systemctl start lightdm
|
|
else
|
|
log_error "Failed to restore - manual intervention required"
|
|
fi
|
|
fi
|
|
|
|
pause
|
|
}
|
|
|
|
action_repair_electron() {
|
|
echo
|
|
echo "This will:"
|
|
echo " 1. Check if the Electron binary is present"
|
|
echo " 2. Download it if missing (~120MB)"
|
|
echo " 3. Fix chrome-sandbox permissions (setuid root)"
|
|
echo " 4. Restart the kiosk display"
|
|
echo
|
|
ask_yes_no "Continue?" "y" || { echo "Cancelled"; pause; return; }
|
|
|
|
sudo systemctl stop lightdm 2>/dev/null || true
|
|
sleep 1
|
|
|
|
# Bare call, not `if ! electron_install_binary; then`: testing a
|
|
# multi-statement function as an if-condition exempts everything
|
|
# inside it from set -e for the duration (e.g. the sandbox chown/
|
|
# chmod below would silently continue past an earlier failure).
|
|
# Capturing $? right after a bare call doesn't have that problem -
|
|
# the exemption only affects whether a nonzero status halts the
|
|
# script, never the actual value $? holds.
|
|
electron_install_binary
|
|
local electron_rc=$?
|
|
if [[ $electron_rc -ne 0 ]]; then
|
|
log_error "Could not install Electron. Check internet and retry."
|
|
pause
|
|
return 1
|
|
fi
|
|
|
|
log_info "Restarting kiosk display..."
|
|
sudo systemctl restart lightdm
|
|
sleep 3
|
|
if systemctl is-active --quiet lightdm && pgrep -f "electron.*main.js" &>/dev/null; then
|
|
log_success "Kiosk display is running"
|
|
else
|
|
log_warning "LightDM started but Electron may still be loading."
|
|
echo " Check: sudo tail -20 $KIOSK_DIR/../electron.log"
|
|
fi
|
|
|
|
pause
|
|
}
|