2023-11-15 19:58:51 +01:00
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -Eeuo pipefail
|
|
|
|
|
|
2023-12-07 23:18:47 +01:00
|
|
|
|
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n"; }
|
|
|
|
|
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
2024-01-19 15:10:40 +01:00
|
|
|
|
warn () { printf "%b%s%b" "\E[1;31m❯ " "Warning: $1" "\E[0m\n" >&2; }
|
2023-12-07 23:18:47 +01:00
|
|
|
|
|
2023-12-09 21:19:08 +01:00
|
|
|
|
trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
|
2023-11-15 19:58:51 +01:00
|
|
|
|
|
2023-11-15 20:54:51 +01:00
|
|
|
|
[ ! -f "/run/entry.sh" ] && error "Script must run inside Docker container!" && exit 11
|
2023-11-15 19:58:51 +01:00
|
|
|
|
[ "$(id -u)" -ne "0" ] && error "Script must be executed with root privileges." && exit 12
|
|
|
|
|
|
2024-01-20 19:59:44 +01:00
|
|
|
|
echo "❯ Starting $APP for Docker v$(</run/version)..."
|
|
|
|
|
echo "❯ For support visit $SUPPORT"
|
|
|
|
|
echo
|
|
|
|
|
|
2023-11-15 19:58:51 +01:00
|
|
|
|
# Docker environment variables
|
|
|
|
|
|
2024-01-14 16:01:15 +01:00
|
|
|
|
: "${TZ:=""}" # System local timezone
|
|
|
|
|
: "${DEBUG:="N"}" # Disable debugging mode
|
|
|
|
|
: "${COUNTRY:=""}" # Country code for mirror
|
|
|
|
|
: "${CONSOLE:="N"}" # Disable console mode
|
|
|
|
|
: "${ALLOCATE:=""}" # Preallocate diskspace
|
|
|
|
|
: "${ARGUMENTS:=""}" # Extra QEMU parameters
|
|
|
|
|
: "${CPU_CORES:="1"}" # Amount of CPU cores
|
|
|
|
|
: "${RAM_SIZE:="1G"}" # Maximum RAM amount
|
|
|
|
|
: "${DISK_SIZE:="16G"}" # Initial data disk size
|
2023-11-15 19:58:51 +01:00
|
|
|
|
|
|
|
|
|
# Helper variables
|
|
|
|
|
|
2024-01-20 19:59:44 +01:00
|
|
|
|
STORAGE="/storage"
|
|
|
|
|
PAGE="/run/shm/index.html"
|
|
|
|
|
TEMPLATE="/var/www/index.html"
|
|
|
|
|
FOOTER1="$APP for Docker v$(</run/version)"
|
|
|
|
|
FOOTER2="<a href='$SUPPORT'>$SUPPORT</a>"
|
|
|
|
|
|
2023-11-15 19:58:51 +01:00
|
|
|
|
KERNEL=$(uname -r | cut -b 1)
|
|
|
|
|
MINOR=$(uname -r | cut -d '.' -f2)
|
|
|
|
|
ARCH=$(dpkg --print-architecture)
|
|
|
|
|
VERS=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1)
|
|
|
|
|
|
2023-11-24 01:37:39 +01:00
|
|
|
|
# Check folder
|
|
|
|
|
|
2024-01-13 20:25:57 +01:00
|
|
|
|
if [ ! -d "$STORAGE" ]; then
|
|
|
|
|
error "Storage folder ($STORAGE) not found!" && exit 13
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ ! -d "/run/shm" ]; then
|
|
|
|
|
if [ -d "/dev/shm" ]; then
|
|
|
|
|
ln -s /dev/shm /run/shm
|
|
|
|
|
else
|
|
|
|
|
error "Folder /dev/shm not found!" && exit 14
|
|
|
|
|
fi
|
|
|
|
|
fi
|
2023-11-24 01:37:39 +01:00
|
|
|
|
|
2023-11-15 19:58:51 +01:00
|
|
|
|
# Cleanup files
|
2024-01-13 20:25:57 +01:00
|
|
|
|
rm -f /run/shm/qemu.*
|
|
|
|
|
rm -f /run/shm/dsm.url
|
2023-11-15 19:58:51 +01:00
|
|
|
|
|
2023-11-24 01:37:39 +01:00
|
|
|
|
# Cleanup dirs
|
|
|
|
|
rm -rf /tmp/dsm
|
|
|
|
|
rm -rf "$STORAGE/tmp"
|
2023-11-16 20:36:30 +01:00
|
|
|
|
|
2023-12-05 06:56:20 +01:00
|
|
|
|
# Helper functions
|
|
|
|
|
|
2023-12-28 03:42:06 +01:00
|
|
|
|
isAlive() {
|
|
|
|
|
local pid=$1
|
|
|
|
|
|
|
|
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pKill() {
|
|
|
|
|
local pid=$1
|
|
|
|
|
|
|
|
|
|
{ kill -15 "$pid" || true; } 2>/dev/null
|
|
|
|
|
|
|
|
|
|
while isAlive "$pid"; do
|
2024-01-20 19:59:44 +01:00
|
|
|
|
sleep 0.2
|
2023-12-28 03:42:06 +01:00
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-20 19:59:44 +01:00
|
|
|
|
fWait() {
|
2023-12-28 03:42:06 +01:00
|
|
|
|
local name=$1
|
|
|
|
|
|
|
|
|
|
while pgrep -f -l "$name" >/dev/null; do
|
2024-01-20 19:59:44 +01:00
|
|
|
|
sleep 0.2
|
2023-12-28 03:42:06 +01:00
|
|
|
|
done
|
2023-12-05 06:56:20 +01:00
|
|
|
|
|
2023-12-28 03:42:06 +01:00
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-20 19:59:44 +01:00
|
|
|
|
fKill() {
|
|
|
|
|
local name=$1
|
|
|
|
|
|
|
|
|
|
{ pkill -f "$name" || true; } 2>/dev/null
|
|
|
|
|
fWait "$name"
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
escape () {
|
|
|
|
|
local s
|
|
|
|
|
s=${1//&/\&}
|
|
|
|
|
s=${s//</\<}
|
|
|
|
|
s=${s//>/\>}
|
|
|
|
|
s=${s//'"'/\"}
|
|
|
|
|
printf -- %s "$s"
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
html()
|
|
|
|
|
{
|
|
|
|
|
local title
|
|
|
|
|
local body
|
|
|
|
|
local footer
|
|
|
|
|
|
|
|
|
|
title=$(escape "$APP")
|
|
|
|
|
title="<title>$title</title>"
|
|
|
|
|
footer=$(escape "$FOOTER1")
|
|
|
|
|
|
|
|
|
|
body=$(escape "$1")
|
|
|
|
|
if [[ "$body" == *"..." ]]; then
|
|
|
|
|
body="<p class=\"loading\">${body/.../}</p>"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
local timeout="4999"
|
|
|
|
|
[ -n "${2:-}" ] && timeout="$2"
|
|
|
|
|
local script="<script>setTimeout(() => { document.location.reload(); }, $timeout);</script>"
|
|
|
|
|
[[ "$timeout" == "0" ]] && script=""
|
|
|
|
|
|
|
|
|
|
local HTML
|
|
|
|
|
HTML=$(<"$TEMPLATE")
|
|
|
|
|
HTML="${HTML/\[1\]/$title}"
|
|
|
|
|
HTML="${HTML/\[2\]/$script}"
|
|
|
|
|
HTML="${HTML/\[3\]/$body}"
|
|
|
|
|
HTML="${HTML/\[4\]/$footer}"
|
|
|
|
|
HTML="${HTML/\[5\]/$FOOTER2}"
|
|
|
|
|
|
|
|
|
|
echo "$HTML" > "$PAGE"
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 17:58:07 +01:00
|
|
|
|
getCountry() {
|
2023-12-05 06:56:20 +01:00
|
|
|
|
local url=$1
|
|
|
|
|
local query=$2
|
2023-12-10 00:26:13 +01:00
|
|
|
|
local rc json result
|
2023-12-05 06:56:20 +01:00
|
|
|
|
|
2023-12-06 07:16:30 +01:00
|
|
|
|
{ json=$(curl -m 5 -H "Accept: application/json" -sfk "$url"); rc=$?; } || :
|
2023-12-05 06:56:20 +01:00
|
|
|
|
(( rc != 0 )) && return 0
|
|
|
|
|
|
|
|
|
|
{ result=$(echo "$json" | jq -r "$query" 2> /dev/null); rc=$?; } || :
|
|
|
|
|
(( rc != 0 )) && return 0
|
|
|
|
|
|
|
|
|
|
[[ ${#result} -ne 2 ]] && return 0
|
|
|
|
|
[[ "${result^^}" == "XX" ]] && return 0
|
|
|
|
|
|
|
|
|
|
COUNTRY="${result^^}"
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 17:58:07 +01:00
|
|
|
|
setCountry() {
|
2023-12-05 06:56:20 +01:00
|
|
|
|
|
2023-12-23 18:46:14 +01:00
|
|
|
|
[[ "${TZ,,}" == "asia/harbin" ]] && COUNTRY="CN"
|
|
|
|
|
[[ "${TZ,,}" == "asia/beijing" ]] && COUNTRY="CN"
|
|
|
|
|
[[ "${TZ,,}" == "asia/urumqi" ]] && COUNTRY="CN"
|
|
|
|
|
[[ "${TZ,,}" == "asia/kashgar" ]] && COUNTRY="CN"
|
|
|
|
|
[[ "${TZ,,}" == "asia/shanghai" ]] && COUNTRY="CN"
|
|
|
|
|
[[ "${TZ,,}" == "asia/chongqing" ]] && COUNTRY="CN"
|
|
|
|
|
|
2023-12-05 06:56:20 +01:00
|
|
|
|
[ -z "$COUNTRY" ] && getCountry "https://api.ipapi.is" ".location.country_code"
|
|
|
|
|
[ -z "$COUNTRY" ] && getCountry "https://ifconfig.co/json" ".country_iso"
|
2024-01-04 11:11:20 +08:00
|
|
|
|
[ -z "$COUNTRY" ] && getCountry "https://api.ip2location.io" ".country_code"
|
2023-12-05 06:56:20 +01:00
|
|
|
|
[ -z "$COUNTRY" ] && getCountry "https://ipinfo.io/json" ".country"
|
|
|
|
|
[ -z "$COUNTRY" ] && getCountry "https://api.myip.com" ".cc"
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 20:25:04 +01:00
|
|
|
|
addPackage() {
|
2023-12-05 06:56:20 +01:00
|
|
|
|
local pkg=$1
|
|
|
|
|
local desc=$2
|
|
|
|
|
|
2023-12-05 07:53:03 +01:00
|
|
|
|
if apt-mark showinstall | grep -qx "$pkg"; then
|
2023-12-05 06:56:20 +01:00
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
2024-01-20 19:59:44 +01:00
|
|
|
|
MSG="Installing $desc..."
|
|
|
|
|
info "$MSG" && html "$MSG"
|
2023-12-05 06:56:20 +01:00
|
|
|
|
|
|
|
|
|
[ -z "$COUNTRY" ] && setCountry
|
|
|
|
|
|
|
|
|
|
if [[ "${COUNTRY^^}" == "CN" ]]; then
|
|
|
|
|
sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list.d/debian.sources
|
|
|
|
|
fi
|
|
|
|
|
|
2024-01-08 01:46:21 +01:00
|
|
|
|
DEBIAN_FRONTEND=noninteractive apt-get -qq update
|
|
|
|
|
DEBIAN_FRONTEND=noninteractive apt-get -qq --no-install-recommends -y install "$pkg" > /dev/null
|
2023-12-05 06:56:20 +01:00
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-20 19:59:44 +01:00
|
|
|
|
# Start webserver
|
|
|
|
|
cp -r /var/www/* /run/shm
|
|
|
|
|
html "Starting $APP for Docker..."
|
|
|
|
|
nginx -e stderr
|
|
|
|
|
|
2023-11-15 19:58:51 +01:00
|
|
|
|
return 0
|