📋 复制 #!/usr/bin/env bash # Generated by shell-gen (https://github.com/yourname/shell-gen) # Generator: VNC 远程桌面 (TigerVNC + 多桌面) # Generated at: 2026-08-04 14:12:09 # OS: Ubuntu / Debian / CentOS / RHEL / Rocky / Alma set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" LOG_PREFIX="[VNC 远程桌面 (TigerVNC + 多桌面)]" log() { echo "${LOG_PREFIX} $*" ; } warn() { echo "${LOG_PREFIX} WARN: $*" >&2 ; } die() { echo "${LOG_PREFIX} ERROR: $*" >&2 ; exit 1 ; } [ "$(id -u)" -eq 0 ] || die "This script must be run as root. Re-run with sudo." # ---- detect distro ---- . /etc/os-release 2>/dev/null || true DISTRO_ID="${ID:-unknown}" DISTRO_LIKE="${ID_LIKE:-}" case "$DISTRO_ID" in ubuntu|debian) PKG="apt-get"; PKG_INSTALL="DEBIAN_FRONTEND=noninteractive apt-get install -y" ;; centos|rhel|rocky|almalinux|ol) PKG="yum"; PKG_INSTALL="yum install -y" ;; fedora) PKG="dnf"; PKG_INSTALL="dnf install -y" ;; *) if echo "$DISTRO_LIKE" | grep -qiE "rhel|centos|fedora"; then PKG="yum"; PKG_INSTALL="yum install -y" elif echo "$DISTRO_LIKE" | grep -qi "debian"; then PKG="apt-get"; PKG_INSTALL="DEBIAN_FRONTEND=noninteractive apt-get install -y" else die "Unsupported distribution: $DISTRO_ID" fi ;; esac log "Detected distro: $DISTRO_ID (package manager: $PKG)" log "Installing VNC + gnome desktop for user 'wxj' on display :15" log "Updating apt cache..." apt-get update log "Installing gnome desktop + TigerVNC..." DEBIAN_FRONTEND=noninteractive apt-get install -y \ ubuntu-desktop-minimal \ dbus-x11 tigervnc-standalone-server tigervnc-common tigervnc-xorg-extension \ xvfb x11vnc x11-utils 2>/dev/null || \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ gnome-session gnome-shell gnome-terminal nautilus metacity \ dbus-x11 tigervnc-standalone-server tigervnc-common \ xvfb x11vnc x11-utils \ xserver-xorg-video-dummy \ gnome-shell-extension-desktop-icons-ng gnome-terminal nautilus-extension-gnome-terminal gnome-tweaks log "Preparing VNC directory..." USER_HOME="$(getent passwd 'wxj' | cut -d: -f6 || echo /root)" if [ "$USER_HOME" = "/root" ] && [ "wxj" != "root" ]; then warn "getent passwd wxj returned home=/root; assuming /home/wxj" USER_HOME="/home/wxj" fi log "User 'wxj' home: $USER_HOME" # Ensure user exists (idempotent — useradd exits 9 if user exists) # Force login shell = /bin/bash so systemd User= can run xstartup id "wxj" >/dev/null 2>&1 || useradd -m -d "$USER_HOME" -s /bin/bash wxj CURRENT_HOME="$(getent passwd "wxj" | cut -d: -f6)" if [ "$CURRENT_HOME" != "$USER_HOME" ]; then warn "Fixing home for user wxj: $CURRENT_HOME -> $USER_HOME" usermod -d "$USER_HOME" -m "wxj" 2>/dev/null || true fi CURRENT_SHELL="$(getent passwd "wxj" | cut -d: -f7)" if [ "$CURRENT_SHELL" != "/bin/bash" ]; then warn "Fixing shell for user wxj: $CURRENT_SHELL -> /bin/bash" usermod -s /bin/bash "wxj" fi [ -d /home ] && chmod 755 /home || true install -d -o "wxj" -g "wxj" -m 0750 "$USER_HOME" install -d -o "wxj" -g "wxj" -m 0700 "$USER_HOME/.vnc" log "Setting VNC password..." PASS='Aa123456' printf "%s\n" "$PASS" | vncpasswd -f > "$USER_HOME/.vnc/passwd" chmod 600 "$USER_HOME/.vnc/passwd" chown "wxj":"wxj" "$USER_HOME/.vnc/passwd" log "Writing xstartup (gnome via dbus-launch)..." cat > "$USER_HOME/.vnc/xstartup" <<'XSTARTUP_EOF' #!/bin/sh unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS export XDG_CURRENT_DESKTOP=ubuntu:GNOME export XDG_SESSION_TYPE=x11 export GNOME_SHELL_SESSION_MODE=ubuntu exec dbus-launch --exit-with-session gnome-session XSTARTUP_EOF chmod +x "$USER_HOME/.vnc/xstartup" log "Writing systemd unit vncserver@.service..." cat > /etc/systemd/system/vncserver@.service <<'UNIT_EOF' [Unit] Description=TigerVNC server on display :%i (gnome) After=syslog.target network.target [Service] Type=simple User=wxj Group=wxj WorkingDirectory=__VNC_HOME__ ExecStartPre=-/usr/bin/vncserver -kill :%i ExecStartPre=-/bin/sh -c 'for f in /tmp/.X%i-lock /tmp/.X11-unix/X%i; do [ -e "$f" ] && rm -f "$f"; done; exit 0' ExecStart=/usr/bin/vncserver -fg :%i -geometry 1920x1080 -depth 24 -localhost=0 ExecStop=/usr/bin/vncserver -kill :%i [Install] WantedBy=multi-user.target UNIT_EOF # Substitute the placeholder with the actual home path sed -i "s|__VNC_HOME__|$USER_HOME|" /etc/systemd/system/vncserver@.service log " WorkingDirectory: $(grep ^WorkingDirectory= /etc/systemd/system/vncserver@.service)" log " Unit written. Verifying WorkingDirectory..." # Check if display :${display} is already in use if ss -xlpn 2>/dev/null | grep -q "/tmp/.X11-unix/X15 "; then EXISTING="$(ss -xlpn 2>/dev/null | grep "/tmp/.X11-unix/X15 " | head -1)" warn "Display :15 is already in use by another X server:" warn " $EXISTING" warn "This machine likely has a physical desktop on :15." warn "Please use a higher display number (e.g. :3 or :10)." die "Display :15 is occupied. Aborting." fi log "Cleaning up stale /tmp/.X11-unix sockets (as root)..." rm -f /tmp/.X15-lock /tmp/.X11-unix/X15 2>/dev/null || true pkill -f "Xvnc.*:15 " 2>/dev/null || true pkill -f "Xtigervnc.*:15" 2>/dev/null || true systemctl daemon-reload systemctl enable vncserver@15.service systemctl restart vncserver@15.service sleep 2 systemctl --no-pager status vncserver@15.service || true log "Verifying port..." ss -ltn | grep ":5915" || warn "Port 5915 not listening yet, give it 5s." log "Done. Connect with VNC Viewer to :5915 (desktop: gnome)"