- consolidated docker run statements

- you can now control the CPU limit of the running AOT process via changing the contents of /root/aot_cpu_limit (gets it's initial value from the env variable AOT_CPU_LIMIT which if set to zero imposes zero limits)
- set limits on log file sizes
This commit is contained in:
Skylar Sadlier 2024-03-07 22:51:44 -07:00
parent fdf2cffd02
commit 61eadc821e
5 changed files with 129 additions and 114 deletions

View File

@ -5,7 +5,13 @@ ENV DEBIAN_FRONTEND noninteractive
ENV LC_ALL C.UTF-8 ENV LC_ALL C.UTF-8
ENV LANG en_US.UTF-8 ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8 ENV LANGUAGE en_US.UTF-8
ENV WINEARCH win64
ENV DISPLAY :0
ENV WINEPREFIX /root/prefix32
ENV AOTDIR "$WINEPREFIX/drive_c/Program Files (x86)/AgeOfTime"
WORKDIR /root/
COPY webaudio.js /root/
RUN dpkg --add-architecture i386 && \ RUN dpkg --add-architecture i386 && \
apt-get update && apt-get -y install python2 python-is-python2 xvfb x11vnc xdotool wget tar supervisor net-tools fluxbox gnupg2 && \ apt-get update && apt-get -y install python2 python-is-python2 xvfb x11vnc xdotool wget tar supervisor net-tools fluxbox gnupg2 && \
wget -O - https://dl.winehq.org/wine-builds/winehq.key | apt-key add - && \ wget -O - https://dl.winehq.org/wine-builds/winehq.key | apt-key add - && \
@ -13,73 +19,60 @@ RUN dpkg --add-architecture i386 && \
apt-get update && apt-get -y install \ apt-get update && apt-get -y install \
wmctrl \ wmctrl \
winehq-stable \ winehq-stable \
libgl1:i386 bzip2 \ # libgl1:i386 bzip2 \
gstreamer1.0-plugins-good \ # gstreamer1.0-plugins-good \
gstreamer1.0-pulseaudio \ # gstreamer1.0-pulseaudio \
gstreamer1.0-tools \ # gstreamer1.0-tools \
libglu1-mesa \ # libglu1-mesa \
libgtk2.0-0 \ # libgtk2.0-0 \
libncursesw5 \ # libncursesw5 \
libopenal1 \ # libopenal1 \
libsdl-image1.2 \ # libsdl-image1.2 \
libsdl-ttf2.0-0 \ # libsdl-ttf2.0-0 \
libsdl1.2debian \ # libsdl1.2debian \
libsndfile1 \ # libsndfile1 \
pulseaudio \ pulseaudio \
ucspi-tcp \
cpulimit && \ cpulimit && \
mkdir /opt/wine-stable/share/wine/mono && wget -O - https://dl.winehq.org/wine/wine-mono/9.0.0/wine-mono-9.0.0-x86.tar.xz | tar -xJv -C /opt/wine-stable/share/wine/mono && \ mkdir /opt/wine-stable/share/wine/mono && wget -O - https://dl.winehq.org/wine/wine-mono/9.0.0/wine-mono-9.0.0-x86.tar.xz | tar -xJv -C /opt/wine-stable/share/wine/mono && \
apt-get -y full-upgrade && apt-get clean && rm -rf /var/lib/apt/lists/* apt-get -y full-upgrade && apt-get clean && rm -rf /var/lib/apt/lists/* && \
# install mono for wine
# the following can be used to skip download and use local file wget -P /mono https://dl.winehq.org/wine/wine-mono/9.0.0/wine-mono-9.0.0-x86.msi && \
# COPY AgeOfTime-29.exe /root/AgeOfTime-29.exe wineboot -i -f -u && \
sleep 10 && \
ENV WINEPREFIX /root/prefix32 xvfb-run msiexec /i /mono/wine-mono-9.0.0-x86.msi /quiet && \
ENV WINEARCH win64 rm -rf /mono/wine-mono-9.0.0-x86.msi && \
ENV DISPLAY :0 # done with wine stuff
ENV AOTDIR "$WINEPREFIX/drive_c/Program Files/AgeOfTime" # download and install AgeOfTime
cd /root && \
RUN wget -P /mono https://dl.winehq.org/wine/wine-mono/9.0.0/wine-mono-9.0.0-x86.msi && \
wineboot -f -u && sleep 10 && xvfb-run msiexec /i /mono/wine-mono-9.0.0-x86.msi /quiet
# wineboot -u && msiexec /i /opt/wine-stable/share/wine/gecko/wine-gecko-2.47.1-x86.msi && \
# rm -rf /mono/wine-mono-4.9.4.msi
# download and install AgeOfTime
RUN cd /root && \
# nohup /usr/bin/Xvfb :0 -screen 0 1024x768x24 && sleep 5 && \
wget https://ageoftime.com/files/AgeOfTime-29.exe && \ wget https://ageoftime.com/files/AgeOfTime-29.exe && \
# mkdir -p "$WINEPREFIX/drive_c/Program Files/" && \
cd "$WINEPREFIX/drive_c/" && \ cd "$WINEPREFIX/drive_c/" && \
chmod +x /root/AgeOfTime-29.exe && \ chmod +x /root/AgeOfTime-29.exe && \
xvfb-run wine /root/AgeOfTime-29.exe -s && \ xvfb-run wine /root/AgeOfTime-29.exe -s && \
rm -f /root/AgeOfTime-29.exe rm -f /root/AgeOfTime-29.exe && \
# mv "$WINEPREFIX/drive_c/Program Files/AgeOfTime" "$WINEPREFIX/drive_c/AgeOfTime" # install noVNC \
wget -O - https://github.com/novnc/noVNC/archive/v1.1.0.tar.gz | tar -xzv -C /root/ && mv /root/noVNC-1.1.0 /root/novnc && ln -s /root/novnc/vnc_lite.html /root/novnc/index.html && \
WORKDIR /root/ wget -O - https://github.com/novnc/websockify/archive/v0.9.0.tar.gz | tar -xzv -C /root/ && mv /root/websockify-0.9.0 /root/novnc/utils/websockify && \
RUN wget -O - https://github.com/novnc/noVNC/archive/v1.1.0.tar.gz | tar -xzv -C /root/ && mv /root/noVNC-1.1.0 /root/novnc && ln -s /root/novnc/vnc_lite.html /root/novnc/index.html && \ # install noVNC audio patch
wget -O - https://github.com/novnc/websockify/archive/v0.9.0.tar.gz | tar -xzv -C /root/ && mv /root/websockify-0.9.0 /root/novnc/utils/websockify # Force vnc_lite.html to be used for novnc, to avoid having the directory listing page.
# Additionally, turn off the control bar. Finally, add a hook to start audio.
# lets copy age of time files instead of install mv /root/webaudio.js /root/novnc/core/webaudio.js && \
# COPY ["AgeOfTime", "$WINEPREFIX/drive_c/Program Files/AgeOfTime"] rm -f /root/novnc/index.html && ln -s /root/novnc/vnc_lite.html /root/novnc/index.html && \
sed -i 's/display:flex/display:none/' /root/novnc/app/styles/base.css && \
# Force vnc_lite.html to be used for novnc, to avoid having the directory listing page. sed -i "/import RFB/a \
# Additionally, turn off the control bar. Finally, add a hook to start audio.
COPY webaudio.js /root/novnc/core/
RUN rm -f /root/novnc/index.html && ln -s /root/novnc/vnc_lite.html /root/novnc/index.html \
&& sed -i 's/display:flex/display:none/' /root/novnc/app/styles/base.css \
&& sed -i "/import RFB/a \
import WebAudio from './core/webaudio.js'" \ import WebAudio from './core/webaudio.js'" \
/root/novnc/vnc_lite.html \ /root/novnc/vnc_lite.html && \
&& sed -i "/function connected(e)/a \ sed -i "/function connected(e)/a \
var wa = new WebAudio('ws://localhost:8081/websockify'); \ var wa = new WebAudio('ws://localhost:8081/websockify'); \
document.getElementsByTagName('canvas')[0].addEventListener('keydown', e => { wa.start(); });" \ document.getElementsByTagName('canvas')[0].addEventListener('keydown', e => { wa.start(); });" \
/root/novnc/vnc_lite.html /root/novnc/vnc_lite.html
COPY restart-aot-crash.sh /root/restart-aot-crash.sh
COPY start-aot.sh /root/start-aot.sh
COPY start.sh /root/start.sh
RUN chmod +x /root/*.sh && \
ln -s "$AOTDIR" /root/AgeOfTime
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
ADD restart-aot-crash.sh /root/restart-aot-crash.sh
ADD start-aot.sh /root/start-aot.sh
RUN chmod +x /root/restart-aot-crash.sh && chmod +x /root/start-aot.sh
EXPOSE 8080 EXPOSE 8080
USER root USER root
CMD ["/usr/bin/supervisord"] CMD ["/root/start.sh"]

View File

@ -1,36 +1,45 @@
#!/bin/bash #!/bin/bash
export DISPLAY=":0.0" export DISPLAY=":0.0"
CPU_LIMIT_FILE="$AOTDIR/aot_cpu_limit"
CURRENT_LIMIT=0
# this script checks for the presence of the wine "Program Error" # Initialize the CPU limit file with AOT_CPU_LIMIT if it's set
# dialog and if it is present it kills AgeOfTime and winedbg if [ ! -z "$AOT_CPU_LIMIT" ]; then
# which causes supervisor to restart it echo "$AOT_CPU_LIMIT" > "$CPU_LIMIT_FILE"
# This script also applies cpu limits if the env variable AOT_CPU_LIMIT is set
# Check if AOT_CPU_LIMIT is set and not zero
if [ -z "$AOT_CPU_LIMIT" ] || [ "$AOT_CPU_LIMIT" -eq 0 ]; then
SKIP_CPU_LIMIT=true
else
SKIP_CPU_LIMIT=false
fi fi
# give the x server time to start
sleep 5;
while true; do while true; do
if wmctrl -l|awk '{$3=""; $2=""; $1=""; print $0}' | grep '^\s*Program Error$'; then if [ -f "$CPU_LIMIT_FILE" ]; then
# echo "AOT Program Error detected" NEW_LIMIT=$(cat "$CPU_LIMIT_FILE")
kill $(pidof AgeOfTime.exe) # Validate NEW_LIMIT is a number greater than zero
kill $(pidof winedbg) if [[ "$NEW_LIMIT" =~ ^[0-9]+$ ]]; then
elif ! $SKIP_CPU_LIMIT && pidof AgeOfTime.exe >/dev/null; then # Check if the limit has changed
# AgeOfTime.exe is running if [ "$NEW_LIMIT" -ne "$CURRENT_LIMIT" ]; then
# Ensure cpulimit is installed and get the PID of AgeOfTime.exe # If so, update CURRENT_LIMIT
CURRENT_LIMIT="$NEW_LIMIT"
# Kill existing cpulimit process if any
AOT_PID=$(pidof AgeOfTime.exe) AOT_PID=$(pidof AgeOfTime.exe)
# Check if cpulimit is already running for AgeOfTime.exe to avoid stacking multiple limits CPULIMIT_PID=$(pgrep -fl "cpulimit.*\-p $(pidof AgeOfTime.exe)" | awk '{print $1}')
if ! pgrep -f "cpulimit.*$AOT_PID" > /dev/null; then if [ ! -z "$CPULIMIT_PID" ]; then
# Apply cpulimit to AgeOfTime.exe to limit it to 2 cores and 50% usage echo "Killing cpulimit process $CPULIMIT_PID"
# Note: cpulimit doesn't directly support core limitation, so we adjust the overall CPU percentage assuming 2 cores kill "$CPULIMIT_PID"
# For more precise control, consider taskset or cgroups fi
cpulimit -p $AOT_PID -l $AOT_CPU_LIMIT # Apply new cpulimit if >= 0
if [ ! -z "$AOT_PID" ] && [ "$NEW_LIMIT" -gt 0 ]; then
echo "Creating cpulimit process (limit=$NEW_LIMIT)"
cpulimit -p "$AOT_PID" -l "$NEW_LIMIT" -b &
fi
fi
fi fi
fi fi
sleep 2 if wmctrl -l | awk '{$3=""; $2=""; $1=""; print $0}' | grep '^\s*Program Error$'; then
kill $(pidof AgeOfTime.exe)
kill $(pidof winedbg)
fi
sleep 1
done done

View File

@ -6,7 +6,7 @@ export HOME=/root
export LANG=en_US.UTF-8 export LANG=en_US.UTF-8
#export WINEDEBUG="+alsa,+pulse,+winealsa,+winepulse,+d3d,+ddraw,+opengl,+winediag", #export WINEDEBUG="+alsa,+pulse,+winealsa,+winepulse,+d3d,+ddraw,+opengl,+winediag",
cd "/root/prefix32/drive_c/Program Files (x86)/AgeOfTime" cd "/root/prefix32/drive_c/Program Files (x86)/AgeOfTime"
#sleep 5 sleep 5
# have to start with wineconsole as wine will cause a crash # have to start with wineconsole as wine will cause a crash
# for some weird reason. wine works fine outside of supervisor though strangely # for some weird reason. wine works fine outside of supervisor though strangely
wineconsole AgeOfTime.exe wineconsole AgeOfTime.exe

3
start.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
/usr/bin/supervisord

View File

@ -28,55 +28,65 @@ priority=1
[program:pulseaudio] [program:pulseaudio]
command=/usr/bin/pulseaudio --disallow-module-loading -vvvv --disallow-exit --exit-idle-time=-1 command=/usr/bin/pulseaudio --disallow-module-loading -vvvv --disallow-exit --exit-idle-time=-1
stdout_logfile=/root/pulseaudio.log stdout_logfile=/root/pulseaudio.log
stdout_logfile_maxbytes=1MB
stderr_logfile_maxbytes=1MB
redirect_stderr=true redirect_stderr=true
priority=1 priority=1
[program:audiostream] ; [program:audiostream]
command=tcpserver localhost 5901 gst-launch-1.0 -q pulsesrc server=/tmp/pulseaudio.socket ! audio/x-raw, channels=2, rate=24000 ! cutter ! opusenc ! webmmux ! fdsink fd=1 ; command=tcpserver localhost 5901 gst-launch-1.0 -q pulsesrc server=/tmp/pulseaudio.socket ! audio/x-raw, channels=2, rate=24000 ! cutter ! opusenc ! webmmux ! fdsink fd=1
stdout_logfile=/root/audiostream.log ; stdout_logfile=/root/audiostream.log
redirect_stderr=true ; stdout_logfile_maxbytes=1MB
priority=1 ; stderr_logfile_maxbytes=1MB
; redirect_stderr=true
; priority=1
[program:websockify_audio] ; [program:websockify_audio]
command=websockify 8081 localhost:5901 ; command=websockify 8081 localhost:5901
stdout_logfile=/root/websockify-audio.log ; stdout_logfile=/root/websockify-audio.log
redirect_stderr=true ; stdout_logfile_maxbytes=1MB
priority=1 ; stderr_logfile_maxbytes=1MB
; redirect_stderr=true
; priority=1
[program:explorer] ; [program:explorer]
command=/opt/wine-stable/bin/wine Explorer.exe ; command=/opt/wine-stable/bin/wine Explorer.exe
autorestart=true ; autorestart=true
stdout_logfile=/dev/fd/1 ; stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0 ; stdout_logfile_maxbytes=0
redirect_stderr=true ; redirect_stderr=true
priority=1 ; priority=1
[program:fluxbox] ; [program:fluxbox]
command=/usr/bin/fluxbox ; command=/usr/bin/fluxbox
autorestart=true ; autorestart=true
stdout_logfile=/dev/fd/1 ; stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0 ; stdout_logfile_maxbytes=0
redirect_stderr=true ; redirect_stderr=true
priority=1 ; priority=1
[program:restart-aot-if-crashed] [program:restart-aot-if-crashed]
command=/bin/bash -c "/root/restart-aot-crash.sh" command=/bin/bash -c "/root/restart-aot-crash.sh"
umask=0022 umask=0022
stderr_logfile = /var/log/supervisor/restart-aot-if-crashed-stderr.log stderr_logfile = /var/log/supervisor/restart-aot-if-crashed-stderr.log
stdout_logfile = /var/log/supervisor/restart-aot-if-crashed-stdout.log stdout_logfile = /var/log/supervisor/restart-aot-if-crashed-stdout.log
stdout_logfile_maxbytes=1MB
stderr_logfile_maxbytes=1MB
autostart=true autostart=true
autorestart=true autorestart=true
user=root user=root
redirect_stderr=true redirect_stderr=true
environment=AOT_CPU_LIMIT=%(ENV_AOT_CPU_LIMIT)s environment=
AOT_CPU_LIMIT="%(ENV_AOT_CPU_LIMIT)s",
AOTDIR="%(ENV_AOTDIR)s"
[program:ageoftime] [program:ageoftime]
command=/root/start-aot.sh command=/root/start-aot.sh
umask=0022 umask=0022
stdout_logfile=/dev/stdout stderr_logfile = /var/log/supervisor/ageoftime-stderr.log
stdout_logfile_maxbytes=0 stdout_logfile = /var/log/supervisor/ageoftime-stdout.log
stderr_logfile=/dev/stderr stdout_logfile_maxbytes=1MB
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=1MB
autostart=true autostart=true
autorestart=true autorestart=true
user=root user=root