Run Sunshine as a service
Goodbye Flatpak Sunshine. Hello AppImage. Until a deb package is available for Debian Bookworm, we can just run sunshine as an AppImage. It is faster to startup and is a little less bloated. The goal here is to run Sunshine as a service managed by supervisord so that it is kept running and is restarted automatically if stopped.
This commit is contained in:
@@ -4,11 +4,22 @@
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"name": "Steam BigPicture",
|
||||
"output": "steam.txt",
|
||||
"cmd": "",
|
||||
"name": "Desktop",
|
||||
"image-path": "desktop.png",
|
||||
"exclude-global-prep-cmd": "true"
|
||||
},
|
||||
{
|
||||
"name": "Steam Big Picture",
|
||||
"image-path": "steam.png",
|
||||
"exclude-global-prep-cmd": "false",
|
||||
"detached": [
|
||||
"\/usr\/games\/steam steam:\/\/open\/bigpicture"
|
||||
],
|
||||
"prep-cmd": [
|
||||
{
|
||||
"do": "",
|
||||
"undo": "\/usr\/bin\/xfce4-close-all-windows"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#
|
||||
min_log_level = info
|
||||
|
||||
# A list of commands to be run before/after all applications.
|
||||
# If any of the prep-commands fail, starting the application is aborted.
|
||||
global_prep_cmd = [{"do":"/usr/bin/xfce4-minimise-all-windows","undo":"/usr/bin/sunshine-stop"}]
|
||||
|
||||
# The origin of the remote endpoint address that is not denied for HTTP method /pin
|
||||
# Could be any of the following values:
|
||||
# pc|lan|wan
|
||||
@@ -95,7 +99,7 @@ min_log_level = info
|
||||
# ping_timeout = 10000
|
||||
|
||||
# The file where configuration for the different applications that Sunshine can run during a stream
|
||||
file_apps = /home/default/sunshine/apps.json
|
||||
file_apps = apps.json
|
||||
|
||||
# Percentage of error correcting packets per data packet in each video frame
|
||||
# Higher values can correct for more network packet loss, but at the cost of increasing bandwidth usage
|
||||
@@ -111,7 +115,7 @@ file_apps = /home/default/sunshine/apps.json
|
||||
#
|
||||
# Unlike simply broadcasting to multiple Client, this will generate distinct video streams.
|
||||
# Note, CPU usage increases for each distinct video stream generated
|
||||
# channels = 1
|
||||
channels = 2
|
||||
|
||||
# The back/select button on the controller
|
||||
# On the Shield, the home and powerbutton are not passed to Moonlight
|
||||
|
||||
@@ -28,7 +28,7 @@ wait_for_x() {
|
||||
wait_for_udev() {
|
||||
MAX=10
|
||||
CT=0
|
||||
while [ ! -f /tmp/.udev-started ]; do
|
||||
while [ ! -f /tmp/.started-udev ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
@@ -53,6 +53,20 @@ wait_for_docker() {
|
||||
echo "DOCKERD RUNNING!"
|
||||
}
|
||||
|
||||
# Wait for desktop to start
|
||||
wait_for_desktop() {
|
||||
MAX=30
|
||||
CT=0
|
||||
while [ ! -f /tmp/.started-desktop ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for Desktop to start"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Fech NVIDIA GPU device (if one exists)
|
||||
get_nvidia_gpu_id() {
|
||||
if [ "${NVIDIA_VISIBLE_DEVICES:-}" == "all" ]; then
|
||||
@@ -67,3 +81,24 @@ get_nvidia_gpu_id() {
|
||||
fi
|
||||
echo ${gpu_select}
|
||||
}
|
||||
|
||||
export_desktop_dbus_session() {
|
||||
if [ ! -f /tmp/.dbus-desktop-session.env ]; then
|
||||
echo "$(dbus-launch)" > /tmp/.dbus-desktop-session.env
|
||||
fi
|
||||
export $(cat /tmp/.dbus-desktop-session.env)
|
||||
}
|
||||
|
||||
# Wait for desktop dbus session to start
|
||||
wait_for_desktop_dbus_session() {
|
||||
MAX=10
|
||||
CT=0
|
||||
while [ ! -f /tmp/.dbus-desktop-session.env ]; do
|
||||
sleep 1
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
echo "FATAL: $0: Gave up waiting for Desktop dbus-launch session to be created"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "**** Installing/upgrading Sunshine via flatpak ****"
|
||||
|
||||
# Install Sunshine
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install --assumeyes --or-update flathub dev.lizardbyte.app.Sunshine
|
||||
# Configure any required overrides
|
||||
flatpak --user override --talk-name=org.freedesktop.Flatpak dev.lizardbyte.app.Sunshine
|
||||
|
||||
# Configure Sunshine as the default browser
|
||||
echo "Configure Sunshine..."
|
||||
sunshine_autostart_desktop="$(cat <<EOF
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
Name=Sunshine
|
||||
Comment=Launch sunshine on login
|
||||
Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 --command=dev.lizardbyte.app.Sunshine.sh dev.lizardbyte.app.Sunshine
|
||||
Icon=sunshine
|
||||
OnlyShowIn=XFCE;
|
||||
RunHook=0
|
||||
StartupNotify=false
|
||||
Terminal=false
|
||||
Hidden=false
|
||||
EOF
|
||||
)"
|
||||
mkdir -p "${USER_HOME:?}/.config/autostart"
|
||||
if [[ ! -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]]; then
|
||||
echo "${sunshine_autostart_desktop:?}" > "${USER_HOME:?}/.config/autostart/Sunshine.desktop"
|
||||
fi
|
||||
# Generate default launchers template:
|
||||
sunshine_apps_data="$(cat <<EOF
|
||||
{
|
||||
"env": {
|
||||
"PATH": "\$(PATH):\$(HOME)\/.local\/bin"
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"name": "Desktop",
|
||||
"image-path": "desktop.png"
|
||||
},
|
||||
{
|
||||
"name": "Low Res Desktop",
|
||||
"image-path": "desktop.png",
|
||||
"prep-cmd": [
|
||||
{
|
||||
"do": "xrandr --output HDMI-1 --mode 1920x1080",
|
||||
"undo": "xrandr --output HDMI-1 --mode 1920x1200"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Steam Big Picture",
|
||||
"image-path": "steam.png",
|
||||
"exclude-global-prep-cmd": "false",
|
||||
"detached": [
|
||||
"flatpak-spawn --host \/usr\/games\/steam steam:\/\/open\/bigpicture"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)"
|
||||
# Generate default sunshine configuration template:
|
||||
# REF: https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/advanced_usage.html
|
||||
sunshine_config_data="$(cat <<EOF
|
||||
# global_prep_cmd
|
||||
# A list of commands to be run before/after all applications.
|
||||
# If any of the prep-commands fail, starting the application is aborted.
|
||||
global_prep_cmd = [{"do":"flatpak-spawn --host /usr/bin/xfce4-minimise-all-windows","undo":"flatpak-spawn --host /usr/bin/sunshine-stop"}]
|
||||
|
||||
# channels
|
||||
# This will generate distinct video streams, unlike simply broadcasting to multiple Clients.
|
||||
# When multicasting, it could be useful to have different configurations for each connected Client.
|
||||
# For instance:
|
||||
# - Clients connected through WAN and LAN have different bitrate constraints.
|
||||
# - Decoders may require different settings for color.
|
||||
channels = 2
|
||||
EOF
|
||||
)"
|
||||
|
||||
mkdir -p "${USER_HOME:?}/.config/sunshine"
|
||||
if [[ ! -f "${USER_HOME:?}/.config/sunshine/apps.json" ]]; then
|
||||
echo "${sunshine_apps_data:?}" > "${USER_HOME:?}/.config/sunshine/apps.json"
|
||||
fi
|
||||
if [[ ! -f "${USER_HOME:?}/.config/sunshine/sunshine.conf " ]]; then
|
||||
echo "${sunshine_config_data:?}" > "${USER_HOME:?}/.config/sunshine/sunshine.conf"
|
||||
fi
|
||||
|
||||
echo "DONE"
|
||||
@@ -19,7 +19,12 @@ trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# CONFIGURE:
|
||||
export $(dbus-launch)
|
||||
# Remove lockfile
|
||||
rm -f /tmp/.started-desktop
|
||||
# Start a session bus instance of dbus-daemon
|
||||
# Note: This script should be the only one that waits for X after exporting this dbus session
|
||||
rm -fv /tmp/.dbus-desktop-session.env
|
||||
export_desktop_dbus_session
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
@@ -30,7 +35,6 @@ if [[ ! -f /tmp/.desktop-apps-updated.lock ]]; then
|
||||
xterm -geometry 200x50+0+0 -ls -e /bin/bash -c "
|
||||
source /usr/bin/install_firefox.sh;
|
||||
source /usr/bin/install_protonup.sh;
|
||||
source /usr/bin/install_sunshine.sh;
|
||||
sleep 1;
|
||||
"
|
||||
touch /tmp/.desktop-apps-updated.lock
|
||||
@@ -40,6 +44,7 @@ fi
|
||||
echo "**** Starting Xfce4 ****"
|
||||
/usr/bin/startxfce4 &
|
||||
desktop_pid=$!
|
||||
touch /tmp/.started-desktop
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
wait "$desktop_pid"
|
||||
|
||||
@@ -13,42 +13,58 @@ source /usr/bin/common-functions.sh
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
_term() {
|
||||
kill -TERM "$sunshine_pid" 2>/dev/null
|
||||
kill -INT "$sunshine_pid" 2>/dev/null
|
||||
sleep 0.5
|
||||
counter=0
|
||||
while kill -0 "$sunshine_pid"; do
|
||||
kill -TERM "$sunshine_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 2
|
||||
done
|
||||
counter=0
|
||||
while kill -0 "$sunshine_pid"; do
|
||||
kill -KILL "$sunshine_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# CONFIGURE:
|
||||
# Install default configurations
|
||||
mkdir -p /home/${USER}/sunshine
|
||||
if [[ ! -f /home/${USER}/sunshine/sunshine.conf ]]; then
|
||||
cp -vf /templates/sunshine/* /home/${USER}/sunshine/
|
||||
# TODO: Set the default encoder '# encoder = nvenc'
|
||||
# nvidia_gpu_id=$(get_nvidia_gpu_id)
|
||||
# if [[ "X${nvidia_gpu_id:-}" != "X" ]]; then
|
||||
# if [[ "all video" == *"${NVIDIA_DRIVER_CAPABILITIES}"* ]]; then
|
||||
# # Check if we have a nvidia GPU available
|
||||
# sed -i 's|^# encoder.*=.*$|encoder = nvenc|' /home/${USER}/sunshine/sunshine.conf
|
||||
# fi
|
||||
# else
|
||||
# # TODO: Enable the vaapi device if not using nvenc
|
||||
# # vainfo --display drm --device /dev/dri/renderD128 2> /dev/null | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)"
|
||||
# # Loop over any render devices
|
||||
# echo
|
||||
# fi
|
||||
mkdir -p "${USER_HOME:?}/.config/sunshine"
|
||||
if [ ! -f "${USER_HOME:?}/.config/sunshine/sunshine.conf" ]; then
|
||||
cp -vf /templates/sunshine/sunshine.conf "${USER_HOME:?}/.config/sunshine/sunshine.conf"
|
||||
fi
|
||||
if [ ! -f "${USER_HOME:?}/.config/sunshine/apps.json" ]; then
|
||||
cp -vf /templates/sunshine/apps.json "${USER_HOME:?}/.config/sunshine/apps.json"
|
||||
fi
|
||||
|
||||
# Reset the default username/password
|
||||
if ([ "X${SUNSHINE_USER:-}" != "X" ] && [ "X${SUNSHINE_PASS:-}" != "X" ]); then
|
||||
sunshine /home/${USER}/sunshine/sunshine.conf --creds ${SUNSHINE_USER:-} ${SUNSHINE_PASS:-}
|
||||
sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" --creds "${SUNSHINE_USER:?}" "${SUNSHINE_PASS:?}"
|
||||
fi
|
||||
# Remove any auto-start scripts from user's .local dir
|
||||
if [ -f "${USER_HOME:?}/.config/autostart/Sunshine.desktop" ]; then
|
||||
rm -fv "${USER_HOME:?}/.config/autostart/Sunshine.desktop"
|
||||
fi
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Wait for the X server to start
|
||||
wait_for_x
|
||||
|
||||
# Start a session bus instance of dbus-daemon
|
||||
wait_for_desktop_dbus_session
|
||||
export_desktop_dbus_session
|
||||
|
||||
# Wait for the desktop to start
|
||||
wait_for_desktop
|
||||
|
||||
# Start the sunshine server
|
||||
sunshine /home/${USER}/sunshine/sunshine.conf &
|
||||
/usr/bin/dumb-init /usr/bin/sunshine "${USER_HOME:?}/.config/sunshine/sunshine.conf" &
|
||||
sunshine_pid=$!
|
||||
|
||||
|
||||
|
||||
@@ -17,9 +17,12 @@ _term() {
|
||||
trap _term SIGTERM SIGINT
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# CONFIGURE:
|
||||
# Remove lockfile
|
||||
rm -f /tmp/.udev-started
|
||||
rm -f /tmp/.started-udev
|
||||
|
||||
|
||||
# EXECUTE PROCESS:
|
||||
# Start udev
|
||||
if command -v udevd &>/dev/null; then
|
||||
unshare --net udevd --daemon &>/dev/null
|
||||
@@ -31,7 +34,7 @@ udevadm monitor &
|
||||
monitor_pid=$!
|
||||
# Touch lockfile
|
||||
sleep 1
|
||||
touch /tmp/.udev-started
|
||||
touch /tmp/.started-udev
|
||||
# Wait for 10 seconds, then request device events from the kernel
|
||||
sleep 10
|
||||
udevadm trigger
|
||||
|
||||
@@ -10,23 +10,40 @@
|
||||
###
|
||||
set -e
|
||||
|
||||
# CATCH TERM SIGNAL:
|
||||
exec >> >(tee -a /tmp/sunshine-exec-run.log) 2>&1
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
date
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
echo "**** Execute sunshine-run ****"
|
||||
echo
|
||||
|
||||
# Trap SIGINT, SIGQUIT, SIGHUP, SIGTERM to forward signals to the child process
|
||||
_term() {
|
||||
pkill -P $$
|
||||
if [ -n "${proc_pid}" ]; then
|
||||
echo " - Forwarding signal $1 to process ${proc_pid}"
|
||||
kill -s "${1}" "${proc_pid}"
|
||||
fi
|
||||
}
|
||||
for sig in INT QUIT HUP TERM; do
|
||||
trap "
|
||||
_term
|
||||
trap - $sig EXIT
|
||||
kill -s $sig "'"$$"' "$sig"
|
||||
done
|
||||
trap _term EXIT
|
||||
trap '_term INT' SIGINT
|
||||
trap '_term QUIT' SIGQUIT
|
||||
trap '_term HUP' SIGHUP
|
||||
trap '_term TERM' SIGTERM
|
||||
|
||||
|
||||
# RUN CHILD PROCESS
|
||||
# Run child process
|
||||
/usr/bin/dumb-init "${@}" &
|
||||
proc_pid=$!
|
||||
echo " - Recording sunshine-run PID '${proc_pid}' in /tmp/sunshine-exec-run.pid"
|
||||
echo "${proc_pid}" > /tmp/sunshine-exec-run.pid
|
||||
|
||||
|
||||
# WAIT FOR CHILD PROCESS:
|
||||
# Wait for child process to exit:
|
||||
echo " - Waiting for PID '${proc_pid}' to exit"
|
||||
wait "$proc_pid"
|
||||
|
||||
# Clean up PID file
|
||||
rm -f /tmp/sunshine-exec-run.pid
|
||||
|
||||
echo "DONE"
|
||||
|
||||
@@ -10,5 +10,48 @@
|
||||
###
|
||||
set -e
|
||||
|
||||
# Terminate any running sunshine-run processes:
|
||||
kill $(ps aux | grep -v grep | grep sunshine-run | awk '{print $2}')
|
||||
exec >> >(tee -a /tmp/sunshine-exec-stop.log) 2>&1
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
date
|
||||
echo
|
||||
echo "-------------------------------"
|
||||
echo
|
||||
echo "**** Execute sunshine-stop ****"
|
||||
echo
|
||||
|
||||
|
||||
process_pid="$(cat /tmp/sunshine-exec-run.pid)"
|
||||
echo " - Found initial sunshine-run PID '${process_pid}'"
|
||||
|
||||
echo " - Sending SIGINT to PID '${process_pid}'"
|
||||
kill -INT "${process_pid}"
|
||||
|
||||
echo " - Checking for other sunshine-run processes '${process_pid}'"
|
||||
for process_pid in $(ps aux | grep -v grep | grep sunshine-run | awk '{print $2}'); do
|
||||
echo " - Sending SIGINT to PID '${process_pid}'"
|
||||
kill -INT "${process_pid}" 2>/dev/null
|
||||
sleep 0.5
|
||||
counter=0
|
||||
while kill -0 "$process_pid" 2>/dev/null; do
|
||||
echo " - Sending SIGTERM to PID '${process_pid}'"
|
||||
kill -TERM "$process_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 2
|
||||
done
|
||||
counter=0
|
||||
while kill -0 "$process_pid" 2>/dev/null; do
|
||||
echo " - Sending SIGKILL to PID '${process_pid}'"
|
||||
kill -KILL "$process_pid" 2>/dev/null
|
||||
counter=$((counter + 1))
|
||||
[ "$counter" -gt 2 ] && break
|
||||
sleep 1
|
||||
done
|
||||
done
|
||||
|
||||
# Clean up PID file
|
||||
rm -f /tmp/sunshine-exec-run.pid
|
||||
|
||||
echo "DONE"
|
||||
|
||||
Reference in New Issue
Block a user