weehong revised this gist 2 weeks ago. Go to revision
1 file changed, 12 insertions, 3 deletions
install-espanso.sh
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | #!/usr/bin/env bash | |
| 2 | 2 | # install-espanso.sh — Install Espanso (text expander) with Wayland or X11 build. | |
| 3 | 3 | # Auto-detects session type; falls back to X11 if Wayland is not active. | |
| 4 | - | # Hardened: session detection, registers service as the invoking user, idempotent. | |
| 4 | + | # Hardened: handles apt temp file permissions, package collisions, and ghost processes. | |
| 5 | 5 | ||
| 6 | 6 | set -euo pipefail | |
| 7 | 7 | IFS=$'\n\t' | |
| @@ -76,6 +76,8 @@ log "Detected: ${PRETTY_NAME:-unknown}, user: $ACTUAL_USER, session: $VARIANT" | |||
| 76 | 76 | ||
| 77 | 77 | export DEBIAN_FRONTEND=noninteractive | |
| 78 | 78 | TEMP_DEB="$(mktemp -t espanso.XXXXXX.deb)" | |
| 79 | + | # Ensure the _apt user can read the temporary file to prevent permission denied errors | |
| 80 | + | chmod 644 "$TEMP_DEB" | |
| 79 | 81 | trap 'rm -f "$TEMP_DEB"' EXIT | |
| 80 | 82 | ||
| 81 | 83 | DEB_NAME="espanso-debian-${VARIANT}-amd64.deb" | |
| @@ -83,11 +85,15 @@ URL="https://github.com/espanso/espanso/releases/latest/download/${DEB_NAME}" | |||
| 83 | 85 | ||
| 84 | 86 | log "Installing prerequisites..." | |
| 85 | 87 | run "apt-get update -qq" | |
| 86 | - | run "apt-get install -y wget libcap2-bin" | |
| 88 | + | run "apt-get install -y wget libcap2-bin psmisc" | |
| 87 | 89 | ||
| 88 | 90 | log "Downloading ${DEB_NAME}..." | |
| 89 | 91 | run "wget -qO '$TEMP_DEB' '$URL'" | |
| 90 | 92 | ||
| 93 | + | log "Removing conflicting Espanso packages (if any)..." | |
| 94 | + | # Suppress output and errors if packages don't exist | |
| 95 | + | run "apt-get remove -y espanso espanso-wayland >/dev/null 2>&1 || true" | |
| 96 | + | ||
| 91 | 97 | log "Installing package..." | |
| 92 | 98 | run "apt-get install -y '$TEMP_DEB'" | |
| 93 | 99 | ||
| @@ -99,6 +105,9 @@ if [[ "$VARIANT" == "wayland" ]]; then | |||
| 99 | 105 | run "setcap 'cap_dac_override+p' '$ESPANSO_BIN'" | |
| 100 | 106 | fi | |
| 101 | 107 | ||
| 108 | + | log "Clearing ghost processes to prevent start timeouts..." | |
| 109 | + | run "sudo -u '$ACTUAL_USER' killall espanso 2>/dev/null || true" | |
| 110 | + | ||
| 102 | 111 | log "Registering & starting espanso service for $ACTUAL_USER..." | |
| 103 | 112 | # Register may fail if already registered — treat that as success. | |
| 104 | 113 | if (( DRY_RUN )); then | |
| @@ -113,4 +122,4 @@ fi | |||
| 113 | 122 | log "Done. Espanso ($VARIANT) installed and started for $ACTUAL_USER." | |
| 114 | 123 | if [[ "$VARIANT" == "wayland" ]]; then | |
| 115 | 124 | log "Wayland note: non-US keyboards must set the layout in ~/.config/espanso/config/default.yml" | |
| 116 | - | fi | |
| 125 | + | fi | |
weehong revised this gist 3 weeks ago. Go to revision
3 files changed, 88 insertions, 45 deletions
READMD.md renamed to README.md
| @@ -16,7 +16,7 @@ How to use the picker: | |||
| 16 | 16 | - `0` runs every option in order | |
| 17 | 17 | - `-1` exits | |
| 18 | 18 | ||
| 19 | - | The menu caches `sudo` credentials up-front so multi-task runs don't keep re-prompting, and falls back to per-user execution for the three scripts that must not run as root (JetBrains Toolbox, IBus Pinyin, Ubuntu Sans Nerd Font). | |
| 19 | + | The menu caches `sudo` credentials up-front so multi-task runs don't keep re-prompting, and falls back to per-user execution for the three scripts that must not run as root (JetBrains Toolbox, IBus Pinyin, Nerd Fonts). | |
| 20 | 20 | ||
| 21 | 21 | ## Available scripts | |
| 22 | 22 | ||
| @@ -33,7 +33,7 @@ The menu caches `sudo` credentials up-front so multi-task runs don't keep re-pro | |||
| 33 | 33 | | 9 | [`install-ipatool.sh`](install-ipatool.sh) | sudo | Installs the latest release of `majd/ipatool` from GitHub. SHA-256 verified against the release `checksums.txt`. Honors `$GITHUB_TOKEN` to avoid API rate limits. | | |
| 34 | 34 | | 10 | [`install-network_drive.sh`](install-network_drive.sh) | sudo | Discovers SMB shares on a Synology NAS and adds them to `/etc/fstab` under `/mnt/Synology` with `x-systemd.automount`. fstab block is managed via begin/end markers so re-runs replace rather than duplicate. Credentials file is `0600`. Best-effort GNOME Dock pin. | | |
| 35 | 35 | | 11 | [`install-ibus-pinyin.sh`](install-ibus-pinyin.sh) | **user** | Installs `ibus-libpinyin` and Simplified Chinese language packs, restarts the IBus daemon, and idempotently adds `('ibus', 'libpinyin')` to GNOME's input sources via `gsettings`. | | |
| 36 | - | | 12 | [`install_font.sh`](install_font.sh) | **user** | Installs the latest Ubuntu Sans Nerd Font to `~/.local/share/fonts/UbuntuSans` and refreshes the font cache. No sudo needed. | | |
| 36 | + | | 12 | [`install-font.sh`](install-font.sh) | **user** | Installs the latest Ubuntu Sans Nerd Font and JetBrains Mono Nerd Font to `~/.local/share/fonts`, then refreshes the font cache. No sudo needed. | | |
| 37 | 37 | ||
| 38 | 38 | "Runs as **user**" entries must be invoked as your normal desktop user, not via `sudo`. The other entries elevate via `sudo` internally and the menu primes `sudo -v` up-front, so you'll only be prompted once. | |
| 39 | 39 | ||
| @@ -46,7 +46,7 @@ If you'd rather skip the menu, each script can be run on its own. Use the right | |||
| 46 | 46 | curl -fsSL https://opengist.rmrf.online/weehong/2de15ba0106a475fa41215159203a63b/raw/HEAD/install-firefox.sh | sudo bash | |
| 47 | 47 | ||
| 48 | 48 | # user scripts (7, 11, 12) — DO NOT use sudo; they install per-user | |
| 49 | - | bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/2de15ba0106a475fa41215159203a63b/raw/HEAD/install_font.sh)" | |
| 49 | + | bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/2de15ba0106a475fa41215159203a63b/raw/HEAD/install-font.sh)" | |
| 50 | 50 | ``` | |
| 51 | 51 | ||
| 52 | 52 | Every script accepts `--help` and `--dry-run` (the latter prints what would happen without executing). For example: | |
install-font.sh
| @@ -1,54 +1,97 @@ | |||
| 1 | - | #!/bin/bash | |
| 1 | + | #!/usr/bin/env bash | |
| 2 | 2 | ||
| 3 | - | # Exit immediately if a command exits with a non-zero status | |
| 4 | - | set -e | |
| 3 | + | set -euo pipefail | |
| 4 | + | IFS=$'\n\t' | |
| 5 | 5 | ||
| 6 | - | FONT_NAME="UbuntuSans" | |
| 7 | - | FONT_ZIP="${FONT_NAME}.zip" | |
| 8 | - | # Simplified directory: removed the "NerdFonts" subfolder | |
| 9 | - | FONT_DIR="$HOME/.local/share/fonts/${FONT_NAME}" | |
| 10 | - | TMP_DIR=$(mktemp -d) | |
| 6 | + | readonly SCRIPT_NAME="${0##*/}" | |
| 7 | + | readonly FONT_BASE_DIR="$HOME/.local/share/fonts" | |
| 8 | + | readonly TMP_DIR="$(mktemp -d)" | |
| 11 | 9 | ||
| 12 | - | echo "Searching for the latest release of $FONT_NAME Nerd Font..." | |
| 10 | + | log() { printf '\033[1;34m[%s]\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*"; } | |
| 11 | + | warn() { printf '\033[1;33m[%s] WARN:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; } | |
| 12 | + | die() { printf '\033[1;31m[%s] ERROR:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; exit 1; } | |
| 13 | 13 | ||
| 14 | - | # Use GitHub API to find the latest release download URL for UbuntuSans.zip | |
| 15 | - | DOWNLOAD_URL=$(curl -s https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest \ | |
| 16 | - | | grep "browser_download_url.*${FONT_ZIP}" \ | |
| 17 | - | | cut -d '"' -f 4) | |
| 14 | + | cleanup() { | |
| 15 | + | rm -rf "$TMP_DIR" | |
| 16 | + | } | |
| 17 | + | trap cleanup EXIT | |
| 18 | 18 | ||
| 19 | - | if [ -z "$DOWNLOAD_URL" ]; then | |
| 20 | - | echo "Error: Could not find the download URL for $FONT_NAME. Check your internet connection or GitHub API limits." | |
| 21 | - | rm -rf "$TMP_DIR" | |
| 22 | - | exit 1 | |
| 19 | + | if (( EUID == 0 )); then | |
| 20 | + | die "Do not run as root. Run as your normal desktop user so fonts install under $HOME." | |
| 23 | 21 | fi | |
| 24 | 22 | ||
| 25 | - | echo "Latest version found!" | |
| 26 | - | echo "Downloading from: $DOWNLOAD_URL" | |
| 23 | + | for tool in curl unzip fc-cache find; do | |
| 24 | + | command -v "$tool" >/dev/null 2>&1 || die "Missing required tool: $tool" | |
| 25 | + | done | |
| 27 | 26 | ||
| 28 | - | # Download the zip file to the temporary directory | |
| 29 | - | curl -L -q "$DOWNLOAD_URL" -o "$TMP_DIR/$FONT_ZIP" | |
| 27 | + | latest_nerd_font_url() { | |
| 28 | + | local asset_name="$1" | |
| 29 | + | local url | |
| 30 | 30 | ||
| 31 | - | echo "Extracting fonts..." | |
| 32 | - | # Ensure unzip is installed (will fail gracefully if not) | |
| 33 | - | if ! command -v unzip &> /dev/null; then | |
| 34 | - | echo "Error: 'unzip' is not installed. Please install it using 'sudo apt install unzip' and try again." | |
| 35 | - | rm -rf "$TMP_DIR" | |
| 36 | - | exit 1 | |
| 37 | - | fi | |
| 31 | + | url="$( | |
| 32 | + | curl -fsSL https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest \ | |
| 33 | + | | grep "browser_download_url.*${asset_name}" \ | |
| 34 | + | | cut -d '"' -f 4 \ | |
| 35 | + | | head -n 1 \ | |
| 36 | + | || true | |
| 37 | + | )" | |
| 38 | + | ||
| 39 | + | [[ -n "$url" ]] || die "Could not find download URL for $asset_name. Check connectivity or GitHub API limits." | |
| 40 | + | printf '%s' "$url" | |
| 41 | + | } | |
| 42 | + | ||
| 43 | + | install_nerd_font() { | |
| 44 | + | local display_name="$1" | |
| 45 | + | local asset_name="$2" | |
| 46 | + | local font_dir="$3" | |
| 47 | + | local download_url="$4" | |
| 48 | + | local zip_path="$TMP_DIR/${asset_name}.zip" | |
| 49 | + | local extract_dir="$TMP_DIR/${asset_name}" | |
| 50 | + | local installed_count | |
| 51 | + | ||
| 52 | + | if [[ -z "$download_url" ]]; then | |
| 53 | + | log "Finding latest $display_name release..." | |
| 54 | + | download_url="$(latest_nerd_font_url "${asset_name}.zip")" | |
| 55 | + | fi | |
| 56 | + | ||
| 57 | + | log "Downloading $display_name..." | |
| 58 | + | curl -fL --retry 3 --retry-delay 2 -o "$zip_path" "$download_url" | |
| 38 | 59 | ||
| 39 | - | unzip -q -o "$TMP_DIR/$FONT_ZIP" -d "$TMP_DIR/extracted" | |
| 60 | + | log "Extracting $display_name..." | |
| 61 | + | mkdir -p "$extract_dir" "$font_dir" | |
| 62 | + | unzip -q -o "$zip_path" -d "$extract_dir" | |
| 40 | 63 | ||
| 41 | - | echo "Installing fonts to $FONT_DIR..." | |
| 42 | - | # Create the simplified font directory if it doesn't exist | |
| 43 | - | mkdir -p "$FONT_DIR" | |
| 64 | + | installed_count="$( | |
| 65 | + | find "$extract_dir" -type f \( -name '*.ttf' -o -name '*.otf' \) \ | |
| 66 | + | -exec cp {} "$font_dir/" \; \ | |
| 67 | + | -printf '.' \ | |
| 68 | + | | wc -c | |
| 69 | + | )" | |
| 44 | 70 | ||
| 45 | - | # Move only the TrueType (.ttf) or OpenType (.otf) files to the fonts directory | |
| 46 | - | find "$TMP_DIR/extracted" -name '*.[ot]tf' -type f -exec cp {} "$FONT_DIR/" \; | |
| 71 | + | [[ "$installed_count" -gt 0 ]] || die "No font files found in ${asset_name}.zip" | |
| 72 | + | find "$font_dir" -type f \( -name '*.ttf' -o -name '*.otf' \) -exec chmod 0644 {} + | |
| 73 | + | log "Installed $installed_count font files to $font_dir" | |
| 74 | + | } | |
| 47 | 75 | ||
| 48 | - | echo "Updating the system font cache..." | |
| 49 | - | fc-cache -f "$FONT_DIR" | |
| 76 | + | mkdir -p "$FONT_BASE_DIR" | |
| 50 | 77 | ||
| 51 | - | echo "Cleaning up temporary files..." | |
| 52 | - | rm -rf "$TMP_DIR" | |
| 78 | + | install_nerd_font \ | |
| 79 | + | "Ubuntu Sans Nerd Font" \ | |
| 80 | + | "UbuntuSans" \ | |
| 81 | + | "$FONT_BASE_DIR/UbuntuSans" \ | |
| 82 | + | "" | |
| 83 | + | ||
| 84 | + | install_nerd_font \ | |
| 85 | + | "JetBrains Mono Nerd Font" \ | |
| 86 | + | "JetBrainsMono" \ | |
| 87 | + | "$FONT_BASE_DIR/JetBrainsMonoNerdFont" \ | |
| 88 | + | "" | |
| 89 | + | ||
| 90 | + | log "Updating font cache..." | |
| 91 | + | fc-cache -f "$FONT_BASE_DIR" | |
| 92 | + | ||
| 93 | + | if command -v fc-match >/dev/null 2>&1; then | |
| 94 | + | log "Resolved terminal font: $(fc-match 'JetBrainsMono Nerd Font Mono')" | |
| 95 | + | fi | |
| 53 | 96 | ||
| 54 | - | echo "Done! $FONT_NAME Nerd Font has been successfully installed." | |
| 97 | + | log "Done. Configure your terminal to use JetBrainsMono Nerd Font Mono for Starship Powerline symbols." | |
menu.sh
| @@ -118,7 +118,7 @@ OPTIONS=( | |||
| 118 | 118 | "10|Install IPATool|install-ipatool.sh|sudo" | |
| 119 | 119 | "11|Mount Synology Network Drive|install-network_drive.sh|sudo" | |
| 120 | 120 | "12|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user" | |
| 121 | - | "13|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user" | |
| 121 | + | "13|Install Nerd Fonts (per-user)|install-font.sh|user" | |
| 122 | 122 | "14|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo" | |
| 123 | 123 | ) | |
| 124 | 124 | ||
| @@ -142,7 +142,7 @@ print_menu() { | |||
| 142 | 142 | echo "--- [ System ] ---" | |
| 143 | 143 | echo " 11) Mount Synology Network Drive" | |
| 144 | 144 | echo " 12) Install IBus Intelligent Pinyin (runs as you, not root)" | |
| 145 | - | echo " 13) Install Ubuntu Sans Nerd Font (runs as you, not root)" | |
| 145 | + | echo " 13) Install Nerd Fonts (runs as you, not root)" | |
| 146 | 146 | echo " 14) Fix Dual-Boot Time (RTC to UTC)" | |
| 147 | 147 | hr | |
| 148 | 148 | echo " 0) Run ALL options (1-14)" | |
| @@ -226,4 +226,4 @@ while true; do | |||
| 226 | 226 | warn "Completed with ${#failures[@]} failure(s): ${failures[*]}" | |
| 227 | 227 | fi | |
| 228 | 228 | echo | |
| 229 | - | done | |
| 229 | + | done | |
weehong revised this gist 3 weeks ago. Go to revision
No changes
weehong revised this gist 3 weeks ago. Go to revision
1 file changed, 47 insertions
install-chrome.sh(file created)
| @@ -0,0 +1,47 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | # | |
| 3 | + | # install-chrome.sh — Native Google Chrome Installer for Ubuntu/Debian | |
| 4 | + | # Downloads and installs the latest official stable release without Snap. | |
| 5 | + | # | |
| 6 | + | # Usage: | |
| 7 | + | # sudo ./install-chrome.sh | |
| 8 | + | ||
| 9 | + | set -euo pipefail | |
| 10 | + | IFS=$'\n\t' | |
| 11 | + | ||
| 12 | + | # Ensure the script is run as root | |
| 13 | + | if (( EUID != 0 )); then | |
| 14 | + | echo "[ERROR] This script must be run as root (via sudo)." >&2 | |
| 15 | + | exit 1 | |
| 16 | + | fi | |
| 17 | + | ||
| 18 | + | echo "[1/4] Installing necessary prerequisites..." | |
| 19 | + | apt-get update -y | |
| 20 | + | apt-get install -y curl gnupg2 ca-certificates | |
| 21 | + | ||
| 22 | + | echo "[2/4] Setting up Google's official repository keys..." | |
| 23 | + | # Create directory for Third-Party APT keys if it doesn't exist | |
| 24 | + | install -d -m 0755 /etc/apt/keyrings | |
| 25 | + | ||
| 26 | + | # Fetch the official signing key and save it securely | |
| 27 | + | curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | \ | |
| 28 | + | gpg --dearmor --yes -o /etc/apt/keyrings/google-chrome.gpg | |
| 29 | + | ||
| 30 | + | # Configure the APT repository to strictly use that signing key | |
| 31 | + | echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \ | |
| 32 | + | > /etc/apt/sources.list.d/google-chrome.list | |
| 33 | + | ||
| 34 | + | echo "[3/4] Fetching package lists and installing Google Chrome..." | |
| 35 | + | apt-get update -y | |
| 36 | + | apt-get install -y google-chrome-stable | |
| 37 | + | ||
| 38 | + | echo "[4/4] Verifying installation..." | |
| 39 | + | if command -v google-chrome &>/dev/null; then | |
| 40 | + | echo "------------------------------------------------------" | |
| 41 | + | echo "SUCCESS: Google Chrome has been installed successfully!" | |
| 42 | + | echo "Version: $(google-chrome --version)" | |
| 43 | + | echo "------------------------------------------------------" | |
| 44 | + | else | |
| 45 | + | echo "[ERROR] Google Chrome installation could not be verified." >&2 | |
| 46 | + | exit 1 | |
| 47 | + | fi | |
weehong revised this gist 3 weeks ago. Go to revision
1 file changed, 31 insertions, 29 deletions
menu.sh
| @@ -106,19 +106,20 @@ run_script() { | |||
| 106 | 106 | # Catalog: number | label | script-filename | mode | |
| 107 | 107 | # (Edit here to add/remove options — the menu loop is data-driven.) | |
| 108 | 108 | OPTIONS=( | |
| 109 | - | "1|Install Firefox (Mozilla APT)|install-firefox.sh|sudo" | |
| 110 | - | "2|Install Thunderbird|install-thunderbird.sh|sudo" | |
| 111 | - | "3|Install 1Password|install-1password.sh|sudo" | |
| 112 | - | "4|Install Espanso (text expander)|install-espanso.sh|sudo" | |
| 113 | - | "5|Install LibreOffice (latest stable .deb)|install-libreoffice.sh|sudo" | |
| 114 | - | "6|Install Visual Studio Code|install-vscode.sh|sudo" | |
| 115 | - | "7|Install JetBrains Toolbox (per-user)|install-jetbrains-toolbox.sh|user" | |
| 116 | - | "8|Install Bruno (API client)|install-bruno.sh|sudo" | |
| 117 | - | "9|Install IPATool|install-ipatool.sh|sudo" | |
| 118 | - | "10|Mount Synology Network Drive|install-network_drive.sh|sudo" | |
| 119 | - | "11|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user" | |
| 120 | - | "12|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user" | |
| 121 | - | "13|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo" | |
| 109 | + | "1|Install Google Chrome|install-chrome.sh|sudo" | |
| 110 | + | "2|Install Firefox (Mozilla APT)|install-firefox.sh|sudo" | |
| 111 | + | "3|Install Thunderbird|install-thunderbird.sh|sudo" | |
| 112 | + | "4|Install 1Password|install-1password.sh|sudo" | |
| 113 | + | "5|Install Espanso (text expander)|install-espanso.sh|sudo" | |
| 114 | + | "6|Install LibreOffice (latest stable .deb)|install-libreoffice.sh|sudo" | |
| 115 | + | "7|Install Visual Studio Code|install-vscode.sh|sudo" | |
| 116 | + | "8|Install JetBrains Toolbox (per-user)|install-jetbrains-toolbox.sh|user" | |
| 117 | + | "9|Install Bruno (API client)|install-bruno.sh|sudo" | |
| 118 | + | "10|Install IPATool|install-ipatool.sh|sudo" | |
| 119 | + | "11|Mount Synology Network Drive|install-network_drive.sh|sudo" | |
| 120 | + | "12|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user" | |
| 121 | + | "13|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user" | |
| 122 | + | "14|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo" | |
| 122 | 123 | ) | |
| 123 | 124 | ||
| 124 | 125 | print_menu() { | |
| @@ -126,24 +127,25 @@ print_menu() { | |||
| 126 | 127 | echo " Ubuntu / Debian Setup Manager" | |
| 127 | 128 | hr | |
| 128 | 129 | echo "--- [ Browsers & Mail ] ---" | |
| 129 | - | echo " 1) Install Firefox" | |
| 130 | - | echo " 2) Install Thunderbird" | |
| 130 | + | echo " 1) Install Google Chrome" | |
| 131 | + | echo " 2) Install Firefox" | |
| 132 | + | echo " 3) Install Thunderbird" | |
| 131 | 133 | echo "--- [ Productivity & Security ] ---" | |
| 132 | - | echo " 3) Install 1Password" | |
| 133 | - | echo " 4) Install Espanso" | |
| 134 | - | echo " 5) Install LibreOffice" | |
| 134 | + | echo " 4) Install 1Password" | |
| 135 | + | echo " 5) Install Espanso" | |
| 136 | + | echo " 6) Install LibreOffice" | |
| 135 | 137 | echo "--- [ Development Tools ] ---" | |
| 136 | - | echo " 6) Install Visual Studio Code" | |
| 137 | - | echo " 7) Install JetBrains Toolbox (runs as you, not root)" | |
| 138 | - | echo " 8) Install Bruno" | |
| 139 | - | echo " 9) Install IPATool" | |
| 138 | + | echo " 7) Install Visual Studio Code" | |
| 139 | + | echo " 8) Install JetBrains Toolbox (runs as you, not root)" | |
| 140 | + | echo " 9) Install Bruno" | |
| 141 | + | echo " 10) Install IPATool" | |
| 140 | 142 | echo "--- [ System ] ---" | |
| 141 | - | echo " 10) Mount Synology Network Drive" | |
| 142 | - | echo " 11) Install IBus Intelligent Pinyin (runs as you, not root)" | |
| 143 | - | echo " 12) Install Ubuntu Sans Nerd Font (runs as you, not root)" | |
| 144 | - | echo " 13) Fix Dual-Boot Time (RTC to UTC)" | |
| 143 | + | echo " 11) Mount Synology Network Drive" | |
| 144 | + | echo " 12) Install IBus Intelligent Pinyin (runs as you, not root)" | |
| 145 | + | echo " 13) Install Ubuntu Sans Nerd Font (runs as you, not root)" | |
| 146 | + | echo " 14) Fix Dual-Boot Time (RTC to UTC)" | |
| 145 | 147 | hr | |
| 146 | - | echo " 0) Run ALL options (1-13)" | |
| 148 | + | echo " 0) Run ALL options (1-14)" | |
| 147 | 149 | echo " -1) Exit" | |
| 148 | 150 | hr | |
| 149 | 151 | } | |
| @@ -162,13 +164,13 @@ resolve_choice() { | |||
| 162 | 164 | return 1 | |
| 163 | 165 | } | |
| 164 | 166 | ||
| 165 | - | ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12 13) | |
| 167 | + | ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12 13 14) | |
| 166 | 168 | ||
| 167 | 169 | prime_sudo || exit 1 | |
| 168 | 170 | ||
| 169 | 171 | while true; do | |
| 170 | 172 | print_menu | |
| 171 | - | read -rp "Enter choices separated by spaces (e.g., 1 6 11), 0 for ALL, -1 to exit: " choices </dev/tty || { | |
| 173 | + | read -rp "Enter choices separated by spaces (e.g., 1 7 12), 0 for ALL, -1 to exit: " choices </dev/tty || { | |
| 172 | 174 | echo; log "Input closed; exiting." | |
| 173 | 175 | break | |
| 174 | 176 | } | |
weehong revised this gist 3 weeks ago. Go to revision
1 file changed, 15 insertions, 16 deletions
timedatectl-fix.sh
| @@ -4,7 +4,7 @@ set -euo pipefail | |||
| 4 | 4 | ||
| 5 | 5 | echo "======================================" | |
| 6 | 6 | echo " Ubuntu Dual-Boot Time Fix Script" | |
| 7 | - | echo " (Local Time Method)" | |
| 7 | + | echo " (UTC Method - Highly Recommended)" | |
| 8 | 8 | echo "======================================" | |
| 9 | 9 | echo | |
| 10 | 10 | ||
| @@ -21,9 +21,9 @@ CURRENT_TZ=$(timedatectl show -p Timezone --value || echo "UTC") | |||
| 21 | 21 | echo "[1/5] Ensuring timezone is set to $CURRENT_TZ..." | |
| 22 | 22 | timedatectl set-timezone "$CURRENT_TZ" | |
| 23 | 23 | ||
| 24 | - | echo "[2/5] Configuring RTC to use Local Time (to match Windows default)..." | |
| 25 | - | # This is the crucial change: '1' sets it to Local Time | |
| 26 | - | timedatectl set-local-rtc 1 --adjust-system-clock | |
| 24 | + | echo "[2/5] Configuring RTC to use UTC (to prevent dual-boot conflicts)..." | |
| 25 | + | # '0' sets the hardware clock to UTC | |
| 26 | + | timedatectl set-local-rtc 0 --adjust-system-clock | |
| 27 | 27 | ||
| 28 | 28 | echo "[3/5] Enabling NTP synchronization..." | |
| 29 | 29 | timedatectl set-ntp true | |
| @@ -37,29 +37,28 @@ timedatectl | |||
| 37 | 37 | ||
| 38 | 38 | echo | |
| 39 | 39 | echo "======================================" | |
| 40 | - | echo " SUCCESS" | |
| 40 | + | echo " SUCCESS - LINUX CONFIGURED" | |
| 41 | 41 | echo "======================================" | |
| 42 | 42 | echo | |
| 43 | 43 | echo "Your system is now configured with:" | |
| 44 | 44 | echo " - Timezone: $CURRENT_TZ" | |
| 45 | - | echo " - RTC stored in Local Time" | |
| 45 | + | echo " - RTC stored in UTC" | |
| 46 | 46 | echo " - NTP synchronization enabled" | |
| 47 | 47 | echo | |
| 48 | - | echo "Note: You can safely ignore any 'RTC in local TZ' warnings" | |
| 49 | - | echo "from timedatectl, as they are expected with this configuration." | |
| 50 | - | echo | |
| 51 | 48 | ||
| 52 | 49 | cat <<'EOF' | |
| 53 | 50 | -------------------------------------------------- | |
| 54 | - | WINDOWS CONFIGURATION (IF NEEDED) | |
| 51 | + | WINDOWS CONFIGURATION (REQUIRED) | |
| 55 | 52 | -------------------------------------------------- | |
| 56 | - | Linux is now expecting the hardware clock to be in Local Time, | |
| 57 | - | which is the default behavior for Windows. | |
| 53 | + | Linux is now correctly expecting the hardware clock to be in UTC. | |
| 54 | + | To make Windows do the same and stop the time from resetting, | |
| 55 | + | you MUST run the following command in Windows. | |
| 58 | 56 | ||
| 59 | - | If you previously added a registry key to force Windows into UTC, | |
| 60 | - | you must remove it. Run this in Windows Administrator CMD: | |
| 57 | + | 1. Boot into Windows. | |
| 58 | + | 2. Open Command Prompt as Administrator. | |
| 59 | + | 3. Run this exact command: | |
| 61 | 60 | ||
| 62 | - | reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /f | |
| 61 | + | reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f | |
| 63 | 62 | ||
| 64 | - | If you never changed Windows time settings, you are completely done! | |
| 63 | + | 4. Restart Windows and sync the time in Settings one last time. | |
| 65 | 64 | EOF | |
weehong revised this gist 3 weeks ago. Go to revision
1 file changed, 15 insertions, 11 deletions
timedatectl-fix.sh
| @@ -3,7 +3,8 @@ | |||
| 3 | 3 | set -euo pipefail | |
| 4 | 4 | ||
| 5 | 5 | echo "======================================" | |
| 6 | - | echo " Linux Dual-Boot Time Fix Script" | |
| 6 | + | echo " Ubuntu Dual-Boot Time Fix Script" | |
| 7 | + | echo " (Local Time Method)" | |
| 7 | 8 | echo "======================================" | |
| 8 | 9 | echo | |
| 9 | 10 | ||
| @@ -20,8 +21,9 @@ CURRENT_TZ=$(timedatectl show -p Timezone --value || echo "UTC") | |||
| 20 | 21 | echo "[1/5] Ensuring timezone is set to $CURRENT_TZ..." | |
| 21 | 22 | timedatectl set-timezone "$CURRENT_TZ" | |
| 22 | 23 | ||
| 23 | - | echo "[2/5] Configuring RTC to use UTC..." | |
| 24 | - | timedatectl set-local-rtc 0 | |
| 24 | + | echo "[2/5] Configuring RTC to use Local Time (to match Windows default)..." | |
| 25 | + | # This is the crucial change: '1' sets it to Local Time | |
| 26 | + | timedatectl set-local-rtc 1 --adjust-system-clock | |
| 25 | 27 | ||
| 26 | 28 | echo "[3/5] Enabling NTP synchronization..." | |
| 27 | 29 | timedatectl set-ntp true | |
| @@ -40,22 +42,24 @@ echo "======================================" | |||
| 40 | 42 | echo | |
| 41 | 43 | echo "Your system is now configured with:" | |
| 42 | 44 | echo " - Timezone: $CURRENT_TZ" | |
| 43 | - | echo " - RTC stored in UTC" | |
| 45 | + | echo " - RTC stored in Local Time" | |
| 44 | 46 | echo " - NTP synchronization enabled" | |
| 45 | 47 | echo | |
| 46 | - | echo "This is the recommended setup for Linux." | |
| 48 | + | echo "Note: You can safely ignore any 'RTC in local TZ' warnings" | |
| 49 | + | echo "from timedatectl, as they are expected with this configuration." | |
| 47 | 50 | echo | |
| 48 | 51 | ||
| 49 | 52 | cat <<'EOF' | |
| 50 | 53 | -------------------------------------------------- | |
| 51 | - | WINDOWS CONFIGURATION REQUIRED | |
| 54 | + | WINDOWS CONFIGURATION (IF NEEDED) | |
| 52 | 55 | -------------------------------------------------- | |
| 53 | - | If you dual-boot with Windows, configure Windows | |
| 54 | - | to also use UTC to prevent clock drift. | |
| 56 | + | Linux is now expecting the hardware clock to be in Local Time, | |
| 57 | + | which is the default behavior for Windows. | |
| 55 | 58 | ||
| 56 | - | Run this in Windows Administrator CMD: | |
| 59 | + | If you previously added a registry key to force Windows into UTC, | |
| 60 | + | you must remove it. Run this in Windows Administrator CMD: | |
| 57 | 61 | ||
| 58 | - | reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /t REG_DWORD /d 1 /f | |
| 62 | + | reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /f | |
| 59 | 63 | ||
| 60 | - | Then reboot Windows once. | |
| 64 | + | If you never changed Windows time settings, you are completely done! | |
| 61 | 65 | EOF | |
weehong revised this gist 4 weeks ago. Go to revision
2 files changed, 6 insertions, 4 deletions
install_font.sh renamed to install-font.sh
File renamed without changes
menu.sh
| @@ -117,7 +117,8 @@ OPTIONS=( | |||
| 117 | 117 | "9|Install IPATool|install-ipatool.sh|sudo" | |
| 118 | 118 | "10|Mount Synology Network Drive|install-network_drive.sh|sudo" | |
| 119 | 119 | "11|Install IBus Intelligent Pinyin (per-user)|install-ibus-pinyin.sh|user" | |
| 120 | - | "12|Install Ubuntu Sans Nerd Font (per-user)|install_font.sh|user" | |
| 120 | + | "12|Install Ubuntu Sans Nerd Font (per-user)|install-font.sh|user" | |
| 121 | + | "13|Fix Dual-Boot Time (RTC to UTC)|timedatectl-fix.sh|sudo" | |
| 121 | 122 | ) | |
| 122 | 123 | ||
| 123 | 124 | print_menu() { | |
| @@ -140,8 +141,9 @@ print_menu() { | |||
| 140 | 141 | echo " 10) Mount Synology Network Drive" | |
| 141 | 142 | echo " 11) Install IBus Intelligent Pinyin (runs as you, not root)" | |
| 142 | 143 | echo " 12) Install Ubuntu Sans Nerd Font (runs as you, not root)" | |
| 144 | + | echo " 13) Fix Dual-Boot Time (RTC to UTC)" | |
| 143 | 145 | hr | |
| 144 | - | echo " 0) Run ALL options (1-12)" | |
| 146 | + | echo " 0) Run ALL options (1-13)" | |
| 145 | 147 | echo " -1) Exit" | |
| 146 | 148 | hr | |
| 147 | 149 | } | |
| @@ -160,7 +162,7 @@ resolve_choice() { | |||
| 160 | 162 | return 1 | |
| 161 | 163 | } | |
| 162 | 164 | ||
| 163 | - | ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12) | |
| 165 | + | ALL_NUMS=(1 2 3 4 5 6 7 8 9 10 11 12 13) | |
| 164 | 166 | ||
| 165 | 167 | prime_sudo || exit 1 | |
| 166 | 168 | ||
| @@ -222,4 +224,4 @@ while true; do | |||
| 222 | 224 | warn "Completed with ${#failures[@]} failure(s): ${failures[*]}" | |
| 223 | 225 | fi | |
| 224 | 226 | echo | |
| 225 | - | done | |
| 227 | + | done | |
weehong revised this gist 4 weeks ago. Go to revision
1 file changed, 61 insertions
timedatectl-fix.sh(file created)
| @@ -0,0 +1,61 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | ||
| 3 | + | set -euo pipefail | |
| 4 | + | ||
| 5 | + | echo "======================================" | |
| 6 | + | echo " Linux Dual-Boot Time Fix Script" | |
| 7 | + | echo "======================================" | |
| 8 | + | echo | |
| 9 | + | ||
| 10 | + | # Ensure running as root | |
| 11 | + | if [[ $EUID -ne 0 ]]; then | |
| 12 | + | echo "Please run as root:" | |
| 13 | + | echo "sudo bash fix-time.sh" | |
| 14 | + | exit 1 | |
| 15 | + | fi | |
| 16 | + | ||
| 17 | + | # Detect current timezone instead of hardcoding | |
| 18 | + | CURRENT_TZ=$(timedatectl show -p Timezone --value || echo "UTC") | |
| 19 | + | ||
| 20 | + | echo "[1/5] Ensuring timezone is set to $CURRENT_TZ..." | |
| 21 | + | timedatectl set-timezone "$CURRENT_TZ" | |
| 22 | + | ||
| 23 | + | echo "[2/5] Configuring RTC to use UTC..." | |
| 24 | + | timedatectl set-local-rtc 0 | |
| 25 | + | ||
| 26 | + | echo "[3/5] Enabling NTP synchronization..." | |
| 27 | + | timedatectl set-ntp true | |
| 28 | + | ||
| 29 | + | echo "[4/5] Restarting time sync daemon (if applicable)..." | |
| 30 | + | systemctl restart systemd-timesyncd 2>/dev/null || true | |
| 31 | + | ||
| 32 | + | echo "[5/5] Final time configuration:" | |
| 33 | + | echo | |
| 34 | + | timedatectl | |
| 35 | + | ||
| 36 | + | echo | |
| 37 | + | echo "======================================" | |
| 38 | + | echo " SUCCESS" | |
| 39 | + | echo "======================================" | |
| 40 | + | echo | |
| 41 | + | echo "Your system is now configured with:" | |
| 42 | + | echo " - Timezone: $CURRENT_TZ" | |
| 43 | + | echo " - RTC stored in UTC" | |
| 44 | + | echo " - NTP synchronization enabled" | |
| 45 | + | echo | |
| 46 | + | echo "This is the recommended setup for Linux." | |
| 47 | + | echo | |
| 48 | + | ||
| 49 | + | cat <<'EOF' | |
| 50 | + | -------------------------------------------------- | |
| 51 | + | WINDOWS CONFIGURATION REQUIRED | |
| 52 | + | -------------------------------------------------- | |
| 53 | + | If you dual-boot with Windows, configure Windows | |
| 54 | + | to also use UTC to prevent clock drift. | |
| 55 | + | ||
| 56 | + | Run this in Windows Administrator CMD: | |
| 57 | + | ||
| 58 | + | reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /t REG_DWORD /d 1 /f | |
| 59 | + | ||
| 60 | + | Then reboot Windows once. | |
| 61 | + | EOF | |
weehong revised this gist 1 month ago. Go to revision
No changes