17 Commits

2 changed files with 82 additions and 78 deletions

View File

@@ -29,7 +29,7 @@ $ installJRMC --help
--compat --compat
Build/install MC without minimum dependency version requirements Build/install MC without minimum dependency version requirements
--mcversion VERSION --mcversion VERSION
Build or install a specific MC version, ex. "33.0.37" or "33" (default: latest) Build or install a specific MC version, ex. "33.0.49" or "33" (default: latest)
--mcrepo REPO --mcrepo REPO
Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: latest official) Specify the MC repository, ex. "bullseye", "bookworm", "noble", etc (default: latest official)
--arch ARCH --arch ARCH
@@ -122,9 +122,9 @@ Multiple services (but not `--service-types`) can be installed at one time using
Install MC from the repository and start/enable `jriver-mediacenter.service` as a user service. Install MC from the repository and start/enable `jriver-mediacenter.service` as a user service.
* `installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 33.0.37` * `installJRMC --install local --compat --restorefile /path/to/license.mjr --mcversion 33.0.49`
Build and install an MC 33.0.37 compatibility RPM locally and activate it using the `/path/to/license.mjr` Build and install an MC 33.0.49 compatibility RPM locally and activate it using the `/path/to/license.mjr`
* `installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user` * `installJRMC --createrepo --createrepo-webroot /srv/jriver/repo --createrepo-user www-user`

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2317
# @file installJRMC # @file installJRMC
# @brief Install JRiver Media Center and associated services # @brief Install JRiver Media Center and associated services
# @description See installJRMC --help or print_help() below for usage # @description See installJRMC --help or print_help() below for usage
#
# Copyright (c) 2021-2024 Bryan C. Roessler # Copyright (c) 2021-2024 Bryan C. Roessler
# This software is released under the Apache License. # This software is released under the Apache License.
# https://www.apache.org/licenses/LICENSE-2.0 # https://www.apache.org/licenses/LICENSE-2.0
@@ -18,12 +18,13 @@
# * Be careful with tabs in heredocs # * Be careful with tabs in heredocs
shopt -s extglob shopt -s extglob
declare -g SCRIPT_VERSION="1.4.5" declare -g SCRIPT_VERSION="1.4.6"
declare -g MC_REPO="bullseye" # should match the MC_VERSION declare -g MC_REPO="bullseye" # should match the MC_VERSION
declare -g MC_VERSION="33.0.37" # Do find all replace declare -g MC_VERSION="33.0.49" # Do find all replace
declare -g BOARD_URL="https://yabb.jriver.com/interact/index.php/board,86.0.html" # MC33 declare -g BOARD_URL="https://yabb.jriver.com/interact/index.php/board,86.0.html" # MC33
declare -ig UPDATE_SWITCH=1 # set to 0 to disable automatic self-update declare -gi UPDATE_SWITCH=1 # set to 0 to disable automatic self-update
declare -g SCRIPT_URL="https://git.bryanroessler.com/bryan/installJRMC/raw/master/installJRMC" declare -g SCRIPT_URL="https://git.bryanroessler.com/bryan/installJRMC/raw/master/installJRMC"
declare -gi DEBUG=${DEBUG:-0} # det default debug and allow DEBUG env override (default: disabled)
# @description Print help text # @description Print help text
print_help() { print_help() {
@@ -113,9 +114,10 @@ print_help() {
# @arg $@ User input # @arg $@ User input
parse_input() { parse_input() {
debug "Running: ${FUNCNAME[0]} $*" debug "Running: ${FUNCNAME[0]} $*"
declare -g BUILD_SWITCH REPO_INSTALL_SWITCH LOCAL_INSTALL_SWITCH \ declare -gi BUILD_SWITCH=0 REPO_INSTALL_SWITCH=0 LOCAL_INSTALL_SWITCH=0 \
CONTAINER_INSTALL_SWITCH COMPAT_SWITCH CREATEREPO_SWITCH UNINSTALL_SWITCH \ CONTAINER_INSTALL_SWITCH=0 COMPAT_SWITCH=0 CREATEREPO_SWITCH=0 UNINSTALL_SWITCH=0 \
YES_SWITCH USER_MC_VERSION USER_MC_REPO MJR_FILE \ YES_SWITCH=0 DEBUG=0
declare -g USER_MC_VERSION USER_MC_REPO MJR_FILE \
BETAPASS SERVICE_TYPE VNCPASS USER_DISPLAY BUILD_TARGET CREATEREPO_TARGET BETAPASS SERVICE_TYPE VNCPASS USER_DISPLAY BUILD_TARGET CREATEREPO_TARGET
local long_opts short_opts input local long_opts short_opts input
long_opts="install:,build::,outputdir:,mcversion:,arch:,mcrepo:,compat," long_opts="install:,build::,outputdir:,mcversion:,arch:,mcrepo:,compat,"
@@ -126,9 +128,6 @@ parse_input() {
long_opts+="vncpass:,display:,container:" long_opts+="vncpass:,display:,container:"
short_opts="+i:b::s:c:uyvdh" short_opts="+i:b::s:c:uyvdh"
# Reset DEBUG and recatch properly with getopt
declare -g DEBUG=0
if input=$(getopt -o $short_opts -l $long_opts -- "$@"); then if input=$(getopt -o $short_opts -l $long_opts -- "$@"); then
eval set -- "$input" eval set -- "$input"
while true; do while true; do
@@ -195,7 +194,7 @@ parse_input() {
shift shift
done done
else else
err "Incorrect options provided"; print_help; exit 1 err "Incorrect option provided, see installJRMC --help"; exit 1
fi fi
# Print some warnings for unsupported argument combinations # Print some warnings for unsupported argument combinations
@@ -288,24 +287,31 @@ init() {
;; ;;
*) *)
err "Auto-detecting distro, this is unreliable and --compat may be required" err "Auto-detecting distro, this is unreliable and --compat may be required"
if command -v dnf &>/dev/null; then for cmd in dnf yum apt-get pacman; do
ID="fedora" if command -v "$cmd" &>/dev/null; then
elif command -v yum &>/dev/null; then case "$cmd" in
ID="centos" dnf) ID="fedora" ;;
COMPAT_SWITCH=1 yum) ID="centos"; COMPAT_SWITCH=1 ;;
elif command -v apt-get &>/dev/null; then apt-get) ID="ubuntu" ;;
ID="ubuntu" pacman) ID="arch" ;;
elif command -v pacman &>/dev/null; then esac
ID="arch" break
else fi
done
if [[ -z $ID ]]; then
err "OS detection failed!" err "OS detection failed!"
ask_ok "Continue with manual installation?" || exit 1 if ask_ok "Continue with manual installation?"; then
debug "Automatically using --install=local for unknown distro" debug "Automatically using --install=local for unknown distro"
ID="unknown" ID="unknown"
REPO_INSTALL_SWITCH=0 REPO_INSTALL_SWITCH=0
BUILD_SWITCH=1 BUILD_SWITCH=1
LOCAL_INSTALL_SWITCH=1 LOCAL_INSTALL_SWITCH=1
else
exit 1
fi fi
fi
;;
esac esac
# Set default targets # Set default targets
@@ -366,6 +372,7 @@ init() {
PKG_UPDATE=(:) PKG_UPDATE=(:)
PKG_QUERY=(:) PKG_QUERY=(:)
PKG_INSTALL_LOCAL() { install_mc_generic; } PKG_INSTALL_LOCAL() { install_mc_generic; }
;;
esac esac
# Don't check for latest MC version if set by user or using --install=repo only # Don't check for latest MC version if set by user or using --install=repo only
@@ -386,12 +393,8 @@ init() {
if [[ -n $USER_MC_VERSION ]]; then if [[ -n $USER_MC_VERSION ]]; then
# Append explicit package version when user provides --mcversion # Append explicit package version when user provides --mcversion
case $ID in case $ID in
fedora|centos|suse) fedora|centos|suse) MC_PKG+="-$MC_VERSION" ;;
MC_PKG+="-$MC_VERSION" debian|ubuntu) MC_PKG+="=$MC_VERSION" ;;
;;
debian|ubuntu)
MC_PKG+="=$MC_VERSION"
;;
esac esac
fi fi
@@ -442,8 +445,8 @@ install_package() {
local -a pkg_array install_flags local -a pkg_array install_flags
local -A pkg_aliases local -A pkg_aliases
local input pkg _pkg local input pkg _pkg
local no_install_check=0 allow_downgrades=0 silent=0 refresh=0 no_gpg_check=0 local -i no_install_check=0 allow_downgrades=0 silent=0 refresh=0 no_gpg_check=0 reinstall=0
local long_opts="no-install-check,allow-downgrades,no-gpg-check,refresh,silent" local long_opts="no-install-check,allow-downgrades,no-gpg-check,refresh,reinstall,silent"
input=$(getopt -o +s -l "$long_opts" -- "$@") || { err "Incorrect options provided"; exit 1; } input=$(getopt -o +s -l "$long_opts" -- "$@") || { err "Incorrect options provided"; exit 1; }
eval set -- "$input" eval set -- "$input"
@@ -454,6 +457,7 @@ install_package() {
--allow-downgrades) allow_downgrades=1 ;; --allow-downgrades) allow_downgrades=1 ;;
--no-gpg-check) no_gpg_check=1 ;; --no-gpg-check) no_gpg_check=1 ;;
--refresh) refresh=1 ;; --refresh) refresh=1 ;;
--reinstall) reinstall=1 ;;
--silent|-s) silent=1 ;; --silent|-s) silent=1 ;;
--) shift; break ;; --) shift; break ;;
esac esac
@@ -502,7 +506,8 @@ install_package() {
# Generate installation flags based on the distribution # Generate installation flags based on the distribution
case $ID in case $ID in
debian|ubuntu) debian|ubuntu)
((allow_downgrades)) && install_flags+=(--allow-downgrades) ;; ((allow_downgrades)) && install_flags+=(--allow-downgrades)
((reinstall)) && install_flags+=(--reinstall) ;;
fedora|centos) fedora|centos)
((allow_downgrades)) && install_flags+=(--allowerasing) ((allow_downgrades)) && install_flags+=(--allowerasing)
((no_gpg_check)) && install_flags+=(--nogpgcheck) ((no_gpg_check)) && install_flags+=(--nogpgcheck)
@@ -557,7 +562,7 @@ install_external_repos() {
# Install mesa-va-drivers-freeworld separately from the RPM using dnf swap # Install mesa-va-drivers-freeworld separately from the RPM using dnf swap
install_mesa_freeworld install_mesa_freeworld
;; ;;
suse) # TODO may eventually be needed if X11_XOrg is not available by default suse) : # TODO may eventually be needed if X11_XOrg is not available by default
# if ! zypper repos | grep -q "X11_XOrg"; then # if ! zypper repos | grep -q "X11_XOrg"; then
# echo "Installing the X11 repository" # echo "Installing the X11 repository"
# execute sudo zypper --non-interactive --quiet addrepo \ # execute sudo zypper --non-interactive --quiet addrepo \
@@ -919,10 +924,12 @@ install_mc_deb() {
execute rm -rf "$extract_dir" execute rm -rf "$extract_dir"
fi fi
# Use --reinstall to make sure local package is installed over repo package
if ! install_package \ if ! install_package \
--no-install-check \ --no-install-check \
--no-gpg-check \ --no-gpg-check \
--allow-downgrades \ --allow-downgrades \
--reinstall \
"$MC_DEB"; then "$MC_DEB"; then
err "Local MC DEB installation failed" err "Local MC DEB installation failed"
err "Only the default MC repo can be used for --install=local" err "Only the default MC repo can be used for --install=local"
@@ -946,7 +953,6 @@ install_mc_rhel() {
# @description Installs Media Center RPM package on SUSE # @description Installs Media Center RPM package on SUSE
install_mc_suse() { install_mc_suse() {
debug "Running: ${FUNCNAME[0]}" debug "Running: ${FUNCNAME[0]}"
install_package --no-install-check --no-gpg-check --allow-downgrades "$MC_RPM" install_package --no-install-check --no-gpg-check --allow-downgrades "$MC_RPM"
} }
@@ -1021,8 +1027,7 @@ install_mc_arch() {
--force \ --force \
--noconfirm \ --noconfirm \
-p mediacenter.pkgbuild; then -p mediacenter.pkgbuild; then
echo "makepkg failed" err "makepkg failed"; exit 1
exit 1
fi fi
popd &>/dev/null || return popd &>/dev/null || return
@@ -1038,8 +1043,8 @@ run_createrepo() {
# Ensure the webroot exists # Ensure the webroot exists
if [[ ! -d $CREATEREPO_WEBROOT ]]; then if [[ ! -d $CREATEREPO_WEBROOT ]]; then
if ! execute sudo -u "$CREATEREPO_USER" mkdir -p "$CREATEREPO_WEBROOT"; then if ! execute sudo -u "$CREATEREPO_USER" mkdir -p "$CREATEREPO_WEBROOT"; then
if ! execute sudo mkdir -p "$CREATEREPO_WEBROOT" && if ! (execute sudo mkdir -p "$CREATEREPO_WEBROOT" \
! execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"; then || execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then
err "Could not create the createrepo-webroot path!" err "Could not create the createrepo-webroot path!"
err "Make sure that the webroot $CREATEREPO_WEBROOT is writable by user $CREATEREPO_USER" err "Make sure that the webroot $CREATEREPO_WEBROOT is writable by user $CREATEREPO_USER"
err "Or change the repo ownership with --createrepo-user" err "Or change the repo ownership with --createrepo-user"
@@ -1049,8 +1054,8 @@ run_createrepo() {
fi fi
# Copy built RPMs to webroot # Copy built RPMs to webroot
if ! execute sudo cp -nf "$MC_RPM" "$CREATEREPO_WEBROOT" || if ! execute sudo cp -nf "$MC_RPM" "$CREATEREPO_WEBROOT" \
! execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"; then || ! execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"; then
err "Could not copy $MC_RPM to $CREATEREPO_WEBROOT" err "Could not copy $MC_RPM to $CREATEREPO_WEBROOT"
return 1 return 1
fi fi
@@ -1063,8 +1068,8 @@ run_createrepo() {
cr_cmd=(sudo createrepo -q "$CREATEREPO_WEBROOT") cr_cmd=(sudo createrepo -q "$CREATEREPO_WEBROOT")
[[ -d $CREATEREPO_WEBROOT/repodata ]] && cr_cmd+=(--update) [[ -d $CREATEREPO_WEBROOT/repodata ]] && cr_cmd+=(--update)
if ! execute "${cr_cmd[@]}" || if ! (execute "${cr_cmd[@]}" \
! execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"; then || execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then
err "createrepo failed" err "createrepo failed"
return 1 return 1
fi fi
@@ -1078,20 +1083,21 @@ link_ssl_certs() {
local mc_cert_link="$MC_ROOT/ca-certificates.crt" local mc_cert_link="$MC_ROOT/ca-certificates.crt"
local -a source_certs=( local -a source_certs=(
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"
"/var/lib/ca-certificates/ca-bundle.pem") "/var/lib/ca-certificates/ca-bundle.pem"
"$MC_ROOT/local-ca-certificates.crt")
target_cert=$(readlink -f "$mc_cert_link") target_cert=$(readlink -f "$mc_cert_link")
[[ -f $target_cert ]] && return 0 [[ -f $target_cert ]] && return 0
for f in "${source_certs[@]}"; do for f in "${source_certs[@]}"; do
if [[ -f $f ]]; then if [[ -f $f ]]; then
if ! execute sudo ln -fs "$f" "$mc_cert_link"; then if execute sudo ln -fs "$f" "$mc_cert_link"; then
err "Symlinking certificate failed" debug "Symlinked $mc_cert_link to $f"
return 1 return 0
fi fi
break
fi fi
done done
err "Certificate symlinking failed"; return 1
} }
# @description Restore the mjr license file from MJR_FILE or other common locations # @description Restore the mjr license file from MJR_FILE or other common locations
@@ -1137,13 +1143,13 @@ restore_license() {
# @arg $2 array List of ports in firewall-cmd format # @arg $2 array List of ports in firewall-cmd format
open_firewall() { open_firewall() {
debug "Running: ${FUNCNAME[0]}" "$*" debug "Running: ${FUNCNAME[0]}" "$*"
local port
local service="$1" local service="$1"
shift shift
local -a f_ports=("$@") # for firewall-cmd local -a f_ports=("$@") # for firewall-cmd
local u_ports="$*" local u_ports="$*"
u_ports="${u_ports// /|}" # concatenate u_ports="${u_ports// /|}" # concatenate
u_ports="${u_ports//-/\:}" # for ufw u_ports="${u_ports//-/\:}" # for ufw
local port
if command -v firewall-cmd &>/dev/null; then if command -v firewall-cmd &>/dev/null; then
if ! sudo firewall-cmd --get-services | grep -q "$service"; then if ! sudo firewall-cmd --get-services | grep -q "$service"; then
@@ -1197,7 +1203,7 @@ set_vnc_pass() {
fi fi
return return
else else
declare -g NOVNCAUTH=1 declare -gi NOVNCAUTH=1
fi fi
} }
@@ -1494,13 +1500,13 @@ disable_btrfs_cow() {
# @description Completely uninstalls MC, services, and firewall rules # @description Completely uninstalls MC, services, and firewall rules
uninstall() { uninstall() {
debug "Running: ${FUNCNAME[0]}" debug "Running: ${FUNCNAME[0]}"
local service unit f i local service type unit f
echo "Stopping and removing all Media Center services" echo "Stopping and removing all Media Center services"
for service in $(compgen -A "function" "service"); do for service in $(compgen -A "function" "service"); do
service="${service##service_}" service="${service##service_}"
for i in user system; do for type in user system; do
set_service_vars "$service" "$i"; set_service_vars "$service" "$type";
for unit in "$SERVICE_NAME" "$TIMER_NAME"; do for unit in "$SERVICE_NAME" "$TIMER_NAME"; do
if "${IS_ACTIVE[@]}" "$unit" || if "${IS_ACTIVE[@]}" "$unit" ||
"${IS_ENABLED[@]}" "$unit"; then "${IS_ENABLED[@]}" "$unit"; then
@@ -1508,16 +1514,10 @@ uninstall() {
fi fi
done done
for f in "$SERVICE_FNAME" "$TIMER_FNAME"; do for f in "$SERVICE_FNAME" "$TIMER_FNAME"; do
[[ -f $f ]] && [[ -f $f ]] && execute sudo rm -f "$f"
execute sudo rm -f "$f"
done done
"${RELOAD[@]}" "${RELOAD[@]}"
unset f
done done
for f in /etc/systemd/system/jriver-*; do
execute sudo rm -f "$f"
done
unset f
done done
echo "Removing MC repositories" echo "Removing MC repositories"
@@ -1530,15 +1530,17 @@ uninstall() {
fi fi
echo "Removing firewall rules" echo "Removing firewall rules"
for service in jriver-mediacenter jriver-xvnc jriver-x11vnc; do
if command -v firewall-cmd &>/dev/null; then if command -v firewall-cmd &>/dev/null; then
execute sudo firewall-cmd --permanent --remove-service=jriver execute sudo firewall-cmd --permanent --remove-service=$service
execute sudo firewall-cmd --permanent --delete-service=jriver execute sudo firewall-cmd --permanent --delete-service=$service
execute sudo firewall-cmd --reload execute sudo firewall-cmd --reload
elif command -v ufw &>/dev/null; then elif command -v ufw &>/dev/null; then
execute sudo ufw delete allow jriver execute sudo ufw delete allow $service
[[ -f "/etc/ufw/applications.d/jriver" ]] && [[ -f /etc/ufw/applications.d/$service ]] &&
execute sudo rm -f /etc/ufw/applications.d/jriver execute sudo rm -f /etc/ufw/applications.d/$service
fi fi
done
echo "Uninstalling JRiver Media Center package" echo "Uninstalling JRiver Media Center package"
if "${PKG_REMOVE[@]}" "${MC_PKG%%=*}"; then # remove version specifier if "${PKG_REMOVE[@]}" "${MC_PKG%%=*}"; then # remove version specifier
@@ -1752,7 +1754,7 @@ main() {
debug() { ((DEBUG)) && echo "Debug: $*"; } debug() { ((DEBUG)) && echo "Debug: $*"; }
err() { echo "Error: $*" >&2; } err() { echo "Error: $*" >&2; }
ask_ok() { ask_ok() {
declare response local response
((YES_SWITCH)) && return 0 ((YES_SWITCH)) && return 0
read -r -p "$* [y/N]: " response read -r -p "$* [y/N]: " response
[[ ${response,,} =~ ^(yes|y)$ ]] [[ ${response,,} =~ ^(yes|y)$ ]]
@@ -1798,7 +1800,9 @@ download() {
fi fi
} }
# Roughly turn debugging on, reparse in parse_input() with getopt # Roughly turn debugging on for pre-init
[[ " $* " =~ ( --debug | -d ) ]] && declare -g DEBUG=1 # Reset and reparse in parse_input() with getopt
[[ " $* " =~ ( --debug | -d ) ]] && DEBUG=1
main "$@" main "$@"
exit