mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-03-15 15:36:44 +08:00
Compare commits
14 Commits
build-2508
...
build-2509
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c44f9e733 | ||
|
|
4d4f528178 | ||
|
|
201c615ce2 | ||
|
|
8cc9e22c91 | ||
|
|
892d2b6f41 | ||
|
|
30dd4290ab | ||
|
|
f900c4bb5a | ||
|
|
6299f04127 | ||
|
|
08551e737e | ||
|
|
bbef7bb5c4 | ||
|
|
b94cc14e2a | ||
|
|
ecc27c2be7 | ||
|
|
ccdfd52b75 | ||
|
|
7ccac8bc9e |
2
.github/workflows/build_img.yaml
vendored
2
.github/workflows/build_img.yaml
vendored
@@ -9,11 +9,13 @@ on:
|
||||
type: choice
|
||||
options:
|
||||
- onecloud
|
||||
- onecloud-pro
|
||||
- cumebox2
|
||||
- chainedbox
|
||||
- vm
|
||||
- e900v22c
|
||||
- octopus-flanet
|
||||
- orangepi-zero
|
||||
- all
|
||||
create_release:
|
||||
description: 'Create GitHub Release'
|
||||
|
||||
@@ -4,13 +4,17 @@ FROM python:3.11.11-slim-bookworm
|
||||
|
||||
LABEL maintainer="mofeng654321@hotmail.com"
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
COPY --from=builder /tmp/lib/* /tmp/lib/
|
||||
COPY --from=builder /tmp/ustreamer/ustreamer /tmp/ustreamer/ustreamer-dump /usr/bin/janus /usr/bin/
|
||||
COPY --from=builder /tmp/wheel/*.whl /tmp/wheel/
|
||||
COPY --from=builder /tmp/ustreamer/libjanus_ustreamer.so /usr/lib/ustreamer/janus/
|
||||
COPY --from=builder /usr/lib/janus/transports/* /usr/lib/janus/transports/
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY --from=builder /tmp/arm64-libs.tar.gz* /tmp/
|
||||
RUN if [ ${TARGETARCH} = arm64 ] && [ -f /tmp/arm64-libs.tar.gz ]; then \
|
||||
cd / && tar -xzf /tmp/arm64-libs.tar.gz && rm -f /tmp/arm64-libs.tar.gz; \
|
||||
fi
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
@@ -41,32 +45,38 @@ RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/' /etc/apt/sources.lis
|
||||
libwebsockets17 \
|
||||
libnss3 \
|
||||
libasound2 \
|
||||
libdrm2 \
|
||||
libx264-164 \
|
||||
libyuv0 \
|
||||
nano \
|
||||
unzip \
|
||||
libavcodec59 \
|
||||
libavformat59 \
|
||||
libavutil57 \
|
||||
libswscale6 \
|
||||
libavfilter8 \
|
||||
libavdevice59 \
|
||||
&& if [ ${TARGETARCH} != arm ] && [ ${TARGETARCH} != arm64 ]; then \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ffmpeg \
|
||||
vainfo \
|
||||
libva2 \
|
||||
libva-drm2 \
|
||||
libva-x11-2 \
|
||||
libdrm2 \
|
||||
mesa-va-drivers \
|
||||
mesa-vdpau-drivers \
|
||||
intel-media-va-driver \
|
||||
i965-va-driver; \
|
||||
fi \
|
||||
&& if [ ${TARGETARCH} = arm ] || [ ${TARGETARCH} = arm64 ]; then \
|
||||
apt-get install -y --no-install-recommends \
|
||||
v4l-utils \
|
||||
libv4l-0; \
|
||||
fi \
|
||||
&& case ${TARGETARCH} in \
|
||||
amd64) \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libavcodec59 libavformat59 libavutil57 \
|
||||
libswscale6 libavfilter8 libavdevice59 \
|
||||
ffmpeg vainfo \
|
||||
libva2 libva-drm2 libva-x11-2 \
|
||||
mesa-va-drivers mesa-vdpau-drivers \
|
||||
intel-media-va-driver i965-va-driver \
|
||||
;; \
|
||||
arm) \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libavcodec59 libavformat59 libavutil57 \
|
||||
libswscale6 libavfilter8 libavdevice59 \
|
||||
v4l-utils libv4l-0 \
|
||||
;; \
|
||||
arm64) \
|
||||
apt-get install -y --no-install-recommends \
|
||||
v4l-utils libv4l-0 \
|
||||
libstdc++6 \
|
||||
libva2 libva-drm2 libva-x11-2 \
|
||||
libvdpau1 ocl-icd-libopencl1 \
|
||||
;; \
|
||||
*) \
|
||||
echo "Unsupported architecture: ${TARGETARCH}" && exit 1 \
|
||||
;; \
|
||||
esac \
|
||||
&& cp /tmp/lib/* /lib/*-linux-*/ \
|
||||
&& pip install --no-cache-dir --root-user-action=ignore --disable-pip-version-check /tmp/wheel/*.whl \
|
||||
&& pip install --no-cache-dir --root-user-action=ignore --disable-pip-version-check pyfatfs \
|
||||
@@ -89,7 +99,8 @@ RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/' /etc/apt/sources.lis
|
||||
&& touch /run/kvmd/ustreamer.sock \
|
||||
&& apt clean \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf /tmp/lib /tmp/wheel
|
||||
&& rm -rf /tmp/lib /tmp/wheel \
|
||||
&& ustreamer -v
|
||||
|
||||
COPY testenv/fakes/vcgencmd scripts/kvmd* /usr/bin/
|
||||
COPY extras/ /usr/share/kvmd/extras/
|
||||
|
||||
@@ -49,27 +49,36 @@ RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/' /etc/apt/sources.lis
|
||||
libusb-1.0-0-dev \
|
||||
libldap2-dev \
|
||||
libsasl2-dev \
|
||||
ffmpeg \
|
||||
libavcodec-dev \
|
||||
libavformat-dev \
|
||||
libavutil-dev \
|
||||
libswscale-dev \
|
||||
libavfilter-dev \
|
||||
libavdevice-dev \
|
||||
vainfo \
|
||||
libva-dev \
|
||||
libva-drm2 \
|
||||
libva-x11-2 \
|
||||
libdrm-dev \
|
||||
mesa-va-drivers \
|
||||
mesa-vdpau-drivers \
|
||||
v4l-utils \
|
||||
libv4l-dev \
|
||||
&& if [ ${TARGETARCH} != arm64 ]; then \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ffmpeg \
|
||||
libavcodec-dev \
|
||||
libavformat-dev \
|
||||
libavutil-dev \
|
||||
libswscale-dev \
|
||||
libavfilter-dev \
|
||||
libavdevice-dev; \
|
||||
fi \
|
||||
&& if [ ${TARGETARCH} != arm ] && [ ${TARGETARCH} != arm64 ]; then \
|
||||
apt-get install -y --no-install-recommends \
|
||||
vainfo \
|
||||
libva-dev \
|
||||
libva-drm2 \
|
||||
libva-x11-2 \
|
||||
intel-media-va-driver \
|
||||
i965-va-driver; \
|
||||
fi \
|
||||
&& if [ ${TARGETARCH} = arm64 ]; then \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ninja-build \
|
||||
zlib1g-dev \
|
||||
libswresample-dev; \
|
||||
fi \
|
||||
&& apt clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -94,12 +103,18 @@ RUN --security=insecure pip config set global.index-url https://pypi.tuna.tsingh
|
||||
pycparser pyelftools pyghmi pygments pyparsing pyotp qrcode requests \
|
||||
semantic-version setproctitle six spidev tabulate urllib3 wrapt xlib \
|
||||
yarl pyserial pyyaml zstandard supervisor pyfatfs pyserial python-periphery \
|
||||
python-ldap python-pam pyrad pyudev pyusb luma.oled pyserial-asyncio
|
||||
python-ldap python-pam pyrad pyudev pyusb luma.oled pyserial-asyncio \
|
||||
&& rm -rf /root/.cache/pip/* /tmp/pip-* \
|
||||
&& if [ ${TARGETARCH} = arm ]; then \
|
||||
umount /root/.cargo 2>/dev/null || true \
|
||||
&& rm -rf /root/.cargo /root/rustup-init.sh; \
|
||||
fi
|
||||
|
||||
# 编译 python vedev库
|
||||
# 编译 python evdev库
|
||||
RUN git clone --depth=1 https://github.com/gvalkov/python-evdev.git /tmp/python-evdev \
|
||||
&& cd /tmp/python-evdev \
|
||||
&& python3 setup.py bdist_wheel --dist-dir /tmp/wheel/
|
||||
&& python3 setup.py bdist_wheel --dist-dir /tmp/wheel/ \
|
||||
&& rm -rf /tmp/python-evdev
|
||||
|
||||
# 编译安装 libnice、libsrtp、libwebsockets 和 janus-gateway
|
||||
RUN git clone --depth=1 https://gitlab.freedesktop.org/libnice/libnice /tmp/libnice \
|
||||
@@ -111,14 +126,14 @@ RUN git clone --depth=1 https://gitlab.freedesktop.org/libnice/libnice /tmp/libn
|
||||
&& tar xf libsrtp-2.2.0.tar.gz \
|
||||
&& cd libsrtp-2.2.0 \
|
||||
&& ./configure --prefix=/usr --enable-openssl \
|
||||
&& make shared_library -j && make install \
|
||||
&& make shared_library -j$(nproc) && make install \
|
||||
&& cd /tmp \
|
||||
&& rm -rf /tmp/libsrtp* \
|
||||
&& git clone --depth=1 https://libwebsockets.org/repo/libwebsockets /tmp/libwebsockets \
|
||||
&& git clone --depth=1 https://github.com/warmcat/libwebsockets /tmp/libwebsockets \
|
||||
&& cd /tmp/libwebsockets \
|
||||
&& mkdir build && cd build \
|
||||
&& cmake -DLWS_MAX_SMP=1 -DLWS_WITHOUT_EXTENSIONS=0 -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_C_FLAGS="-fpic" .. \
|
||||
&& make -j && make install \
|
||||
&& make -j$(nproc) && make install \
|
||||
&& cd /tmp \
|
||||
&& rm -rf /tmp/libwebsockets \
|
||||
&& git clone --depth=1 https://github.com/meetecho/janus-gateway.git /tmp/janus-gateway \
|
||||
@@ -127,19 +142,40 @@ RUN git clone --depth=1 https://gitlab.freedesktop.org/libnice/libnice /tmp/libn
|
||||
&& ./configure --enable-static --enable-websockets --enable-plugin-audiobridge \
|
||||
--disable-data-channels --disable-rabbitmq --disable-mqtt --disable-all-plugins \
|
||||
--disable-all-loggers --prefix=/usr \
|
||||
&& make -j && make install \
|
||||
&& make -j$(nproc) && make install \
|
||||
&& cd /tmp \
|
||||
&& rm -rf /tmp/janus-gateway
|
||||
|
||||
# 编译 Rockchip MPP、RGA 和 FFmpeg(仅 arm64)
|
||||
RUN if [ ${TARGETARCH} = arm64 ]; then \
|
||||
git clone -b jellyfin-mpp --depth=1 https://github.com/nyanmisaka/mpp.git /tmp/rkmpp \
|
||||
&& mkdir -p /tmp/rkmpp/rkmpp_build && cd /tmp/rkmpp/rkmpp_build \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DBUILD_TEST=OFF .. \
|
||||
&& make -j$(nproc) \
|
||||
&& make install \
|
||||
&& git clone -b jellyfin-rga --depth=1 https://github.com/nyanmisaka/rk-mirrors.git /tmp/rkrga \
|
||||
&& cd /tmp/ \
|
||||
&& meson setup rkrga rkrga_build --prefix=/usr --libdir=lib --buildtype=release -Dcpp_args=-fpermissive -Dlibdrm=false -Dlibrga_demo=false \
|
||||
&& meson configure rkrga_build > /dev/null \
|
||||
&& ninja -C rkrga_build install \
|
||||
&& git clone --depth=1 https://github.com/nyanmisaka/ffmpeg-rockchip.git /tmp/ffmpeg-rockchip \
|
||||
&& cd /tmp/ffmpeg-rockchip \
|
||||
&& ./configure --prefix=/usr --enable-gpl --enable-version3 --enable-libdrm --enable-rkmpp --enable-rkrga \
|
||||
--enable-libv4l2 --enable-libx264 --enable-shared --disable-programs \
|
||||
--disable-doc --disable-htmlpages --disable-manpages --disable-network --disable-protocols \
|
||||
--disable-decoders --disable-debug --disable-alsa \
|
||||
&& make -j$(nproc) \
|
||||
&& make install \
|
||||
&& rm -rf /tmp/rkmpp /tmp/rkrga /tmp/ffmpeg-rockchip; \
|
||||
fi
|
||||
|
||||
# 编译 ustreamer
|
||||
RUN echo "Building ustreamer with timestamp cache bust" \
|
||||
&& sed --in-place --expression 's|^#include "refcount.h"$|#include "../refcount.h"|g' /usr/include/janus/plugins/plugin.h \
|
||||
&& TIMESTAMP=$(date +%s%N) \
|
||||
&& git clone --depth=1 https://github.com/mofeng-git/ustreamer /tmp/ustreamer-${TIMESTAMP} \
|
||||
&& make -j WITH_PYTHON=1 WITH_JANUS=1 WITH_FFMPEG=1 -C /tmp/ustreamer-${TIMESTAMP} \
|
||||
&& /tmp/ustreamer-${TIMESTAMP}/ustreamer -v \
|
||||
&& cp /tmp/ustreamer-${TIMESTAMP}/python/dist/*.whl /tmp/wheel/ \
|
||||
&& mv /tmp/ustreamer-${TIMESTAMP} /tmp/ustreamer
|
||||
RUN sed --in-place --expression 's|^#include "refcount.h"$|#include "../refcount.h"|g' /usr/include/janus/plugins/plugin.h \
|
||||
&& git clone --depth=1 https://github.com/mofeng-git/ustreamer /tmp/ustreamer \
|
||||
&& make -j$(nproc) WITH_PYTHON=1 WITH_JANUS=1 WITH_FFMPEG=1 -C /tmp/ustreamer \
|
||||
&& /tmp/ustreamer/ustreamer -v \
|
||||
&& /tmp/ustreamer/ustreamer-dump -v \
|
||||
&& cp /tmp/ustreamer/python/dist/*.whl /tmp/wheel/
|
||||
|
||||
# 复制必要的库文件
|
||||
RUN mkdir /tmp/lib \
|
||||
@@ -148,4 +184,11 @@ RUN mkdir /tmp/lib \
|
||||
libevent-*.so.* libjpeg.so.* libyuv.so.* libnice.so.* \
|
||||
/tmp/lib/ \
|
||||
&& find /usr/lib -name "libsrtp2.so.*" -exec cp {} /tmp/lib/ \; \
|
||||
&& find /usr/lib -name "libwebsockets.so.*" -exec cp {} /tmp/lib/ \;
|
||||
&& find /usr/lib -name "libwebsockets.so.*" -exec cp {} /tmp/lib/ \; \
|
||||
&& if [ ${TARGETARCH} = arm64 ]; then \
|
||||
find /usr/lib -name "libav*.so.*" -exec cp {} /tmp/lib/ \; \
|
||||
&& find /usr/lib -name "libsw*.so.*" -exec cp {} /tmp/lib/ \; \
|
||||
&& find /usr/lib -name "libpostproc.so.*" -exec cp {} /tmp/lib/ \; \
|
||||
&& find /usr/lib -name "librockchip*" -exec cp {} /tmp/lib/ \; \
|
||||
&& find /usr/lib -name "librga.so.*" -exec cp {} /tmp/lib/ \; ; \
|
||||
fi
|
||||
|
||||
@@ -59,7 +59,7 @@ build_target() {
|
||||
onecloud)
|
||||
onecloud_rootfs
|
||||
local arch="armhf"
|
||||
local device_type="gpio"
|
||||
local device_type="gpio-onecloud"
|
||||
local network_type="systemd-networkd"
|
||||
;;
|
||||
cumebox2)
|
||||
@@ -97,6 +97,20 @@ build_target() {
|
||||
local network_type=""
|
||||
NEED_PREPARE_DNS=true
|
||||
;;
|
||||
onecloud-pro)
|
||||
onecloud_pro_rootfs
|
||||
local arch="aarch64"
|
||||
local device_type="gpio-onecloud-pro video1"
|
||||
local network_type=""
|
||||
NEED_PREPARE_DNS=true
|
||||
;;
|
||||
orangepi-zero)
|
||||
orangepizero_rootfs
|
||||
local arch="armhf"
|
||||
local device_type=""
|
||||
local network_type=""
|
||||
NEED_PREPARE_DNS=true
|
||||
;;
|
||||
*)
|
||||
echo "错误:未知或不支持的目标 '$target'" >&2
|
||||
exit 1
|
||||
@@ -124,12 +138,18 @@ build_target() {
|
||||
chainedbox)
|
||||
pack_img "Chainedbox"
|
||||
;;
|
||||
e900v22c)
|
||||
e900v22c)
|
||||
pack_img "E900v22c"
|
||||
;;
|
||||
octopus-flanet)
|
||||
octopus-flanet)
|
||||
pack_img "Octopus-Flanet"
|
||||
;;
|
||||
onecloud-pro)
|
||||
pack_img "Onecloud-Pro"
|
||||
;;
|
||||
orangepi-zero)
|
||||
pack_img "Orangepi-Zero"
|
||||
;;
|
||||
*)
|
||||
echo "错误:未知的打包类型 for '$target'" >&2
|
||||
;;
|
||||
@@ -148,7 +168,7 @@ build_target() {
|
||||
# 检查是否提供了目标参数
|
||||
if [ -z "$1" ]; then
|
||||
echo "用法: $0 <target|all>"
|
||||
echo "可用目标: onecloud, cumebox2, chainedbox, vm, e900v22c, octopus-flanet"
|
||||
echo "可用目标: onecloud, cumebox2, chainedbox, vm, e900v22c, octopus-flanet, onecloud-pro, orangepi-zero"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -167,6 +187,8 @@ if [ "$1" = "all" ]; then
|
||||
build_target "vm"
|
||||
build_target "e900v22c"
|
||||
build_target "octopus-flanet"
|
||||
build_target "onecloud-pro"
|
||||
build_target "orangepi-zero"
|
||||
echo "信息:所有目标构建完成。"
|
||||
else
|
||||
build_target "$1"
|
||||
|
||||
@@ -244,6 +244,37 @@ download_file_if_missing() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# 下载 rc.local 文件
|
||||
download_rc_local() {
|
||||
local platform_id="$1"
|
||||
local rc_local_path="$SRCPATH/image/$platform_id/rc.local"
|
||||
local relative_path="image/$platform_id/rc.local"
|
||||
local remote_url="$REMOTE_PREFIX/$relative_path"
|
||||
|
||||
echo "信息:检查是否需要下载 rc.local 文件 ($platform_id)..."
|
||||
|
||||
# 如果本地文件不存在,尝试下载
|
||||
if [ ! -f "$rc_local_path" ]; then
|
||||
echo "信息:本地 rc.local 文件不存在,尝试从远程下载..."
|
||||
ensure_dir "$(dirname "$rc_local_path")"
|
||||
|
||||
if curl -sSL --fail "$remote_url" -o "$rc_local_path"; then
|
||||
echo "信息:成功下载 rc.local 文件:$remote_url"
|
||||
# 在 GitHub Actions 环境中记录下载的文件
|
||||
if is_github_actions; then
|
||||
echo "$rc_local_path" >> "$DOWNLOADED_FILES_LIST"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
echo "信息:远程 rc.local 文件不存在或下载失败:$remote_url"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "信息:使用本地 rc.local 文件:$rc_local_path"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理下载的文件(仅在 GitHub Actions 环境中)
|
||||
cleanup_downloaded_files() {
|
||||
if is_github_actions && [[ -f "$DOWNLOADED_FILES_LIST" ]]; then
|
||||
|
||||
@@ -10,7 +10,7 @@ onecloud_rootfs() {
|
||||
local bootfs_sparse="$TMPDIR/6.boot.PARTITION.sparse"
|
||||
local rootfs_sparse="$TMPDIR/7.rootfs.PARTITION.sparse"
|
||||
local bootfs_loopdev="" # 存储 bootfs 使用的 loop 设备
|
||||
local add_size_mb=400
|
||||
local add_size_mb=600
|
||||
|
||||
echo "信息:准备 Onecloud Rootfs..."
|
||||
ensure_dir "$TMPDIR"
|
||||
@@ -66,9 +66,10 @@ onecloud_rootfs() {
|
||||
}
|
||||
|
||||
cumebox2_rootfs() {
|
||||
local source_image="$SRCPATH/image/cumebox2/Armbian_25.2.2_Khadas-vim1_bookworm_current_6.12.17_minimal.img"
|
||||
local source_image="$SRCPATH/image/cumebox2/Armbian_24.8.1_Khadas-vim1_bookworm_current_6.6.47_minimal.img"
|
||||
local target_image="$TMPDIR/rootfs.img"
|
||||
local offset=$((8192 * 512))
|
||||
local add_size_mb=900
|
||||
|
||||
echo "信息:准备 Cumebox2 Rootfs..."
|
||||
ensure_dir "$TMPDIR"
|
||||
@@ -78,6 +79,9 @@ cumebox2_rootfs() {
|
||||
|
||||
cp "$source_image" "$target_image" || { echo "错误:复制 Cumebox2 原始镜像失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:扩展镜像文件 (${add_size_mb}MB)..."
|
||||
sudo dd if=/dev/zero bs=1M count="$add_size_mb" >> "$target_image" || { echo "错误:扩展镜像文件失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:调整镜像分区大小..."
|
||||
sudo parted -s "$target_image" resizepart 1 100% || { echo "错误:使用 parted 调整分区大小失败" >&2; exit 1; }
|
||||
|
||||
@@ -159,7 +163,7 @@ e900v22c_rootfs() {
|
||||
local source_image="$SRCPATH/image/e900v22c/Armbian_23.08.0_amlogic_s905l3a_bookworm_5.15.123_server_2023.08.01.img"
|
||||
local target_image="$TMPDIR/rootfs.img"
|
||||
local offset=$((532480 * 512))
|
||||
local add_size_mb=400
|
||||
local add_size_mb=600
|
||||
|
||||
echo "信息:准备 E900V22C Rootfs..."
|
||||
ensure_dir "$TMPDIR"
|
||||
@@ -188,11 +192,11 @@ e900v22c_rootfs() {
|
||||
}
|
||||
|
||||
octopus_flanet_rootfs() {
|
||||
local source_image="$SRCPATH/image/octopus-flanet/Armbian_24.11.0_amlogic_s912_bookworm_6.1.114_server_2024.11.01.img"
|
||||
local source_image="$SRCPATH/image/octopus-flanet/Armbian_25.05.0_amlogic_s912_bookworm_6.1.129_server_2025.03.02.img"
|
||||
local target_image="$TMPDIR/rootfs.img"
|
||||
local boot_offset=$((8192 * 512))
|
||||
local rootfs_offset=$((1056768 * 512))
|
||||
local add_size_mb=400
|
||||
local add_size_mb=600
|
||||
local bootfs_loopdev=""
|
||||
|
||||
echo "信息:准备 Octopus-Planet Rootfs..."
|
||||
@@ -231,6 +235,71 @@ octopus_flanet_rootfs() {
|
||||
echo "信息:Octopus-Planet Rootfs 准备完成,loop 设备 $LOOPDEV 已就绪。"
|
||||
}
|
||||
|
||||
onecloud_pro_rootfs() {
|
||||
local source_image="$SRCPATH/image/onecloud-pro/Armbian-by-SilentWind_24.5.0_amlogic_Onecloud-Pro_jammy_6.6.28_server.img"
|
||||
local target_image="$TMPDIR/rootfs.img"
|
||||
local boot_offset=$((8192 * 512))
|
||||
local rootfs_offset=$((1056768 * 512))
|
||||
local add_size_mb=600
|
||||
local bootfs_loopdev=""
|
||||
|
||||
echo "信息:准备 Octopus-Planet Rootfs..."
|
||||
ensure_dir "$TMPDIR"; ensure_dir "$BOOTFS"
|
||||
|
||||
# 自动下载源镜像文件(如果不存在)
|
||||
download_file_if_missing "$source_image" || { echo "错误:下载 Octopus-Planet 原始镜像失败" >&2; exit 1; }
|
||||
|
||||
cp "$source_image" "$target_image" || { echo "错误:复制 Octopus-Planet 原始镜像失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:调整镜像分区大小 (分区 2)..."
|
||||
sudo parted -s "$target_image" resizepart 2 100% || { echo "错误:使用 parted 调整分区 2 大小失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:设置 rootfs 分区的 loop 设备..."
|
||||
find_loop_device # 找 loop 给 rootfs
|
||||
echo "信息:将 $target_image (偏移 $rootfs_offset) 关联到 $LOOPDEV..."
|
||||
sudo losetup --offset "$rootfs_offset" "$LOOPDEV" "$target_image" || { echo "错误:设置 rootfs 分区 loop 设备 $LOOPDEV 失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:检查并调整文件系统大小 (在 loop 设备上)..."
|
||||
sudo e2fsck -f -y "$LOOPDEV" || { echo "警告:e2fsck 检查 $LOOPDEV 失败" >&2; exit 1; }
|
||||
sudo resize2fs "$LOOPDEV" || { echo "错误:resize2fs 调整 $LOOPDEV 大小失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:Octopus-Planet Rootfs 准备完成,loop 设备 $LOOPDEV 已就绪。"
|
||||
}
|
||||
|
||||
orangepizero_rootfs() {
|
||||
local source_image="$SRCPATH/image/orangepi-zero/Armbian_community_25.11.0-trunk.208_Orangepizero_bookworm_current_6.12.47_minimal.img"
|
||||
local target_image="$TMPDIR/rootfs.img"
|
||||
local offset=$((8192 * 512))
|
||||
local add_size_mb=600
|
||||
|
||||
echo "信息:准备 Orange Pi Zero Rootfs..."
|
||||
ensure_dir "$TMPDIR"
|
||||
|
||||
echo "信息:下载或使用本地 Orange Pi Zero 原始镜像..."
|
||||
download_file_if_missing "$source_image" || { echo "错误:下载 Orange Pi Zero 原始镜像失败" >&2; exit 1; }
|
||||
|
||||
cp "$source_image" "$target_image" || { echo "错误:复制 Orange Pi Zero 原始镜像失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:扩展镜像文件 (${add_size_mb}MB)..."
|
||||
sudo dd if=/dev/zero bs=1M count="$add_size_mb" >> "$target_image" || { echo "错误:扩展镜像文件失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:调整镜像分区大小..."
|
||||
sudo parted -s "$target_image" resizepart 1 100% || { echo "错误:使用 parted 调整分区大小失败" >&2; exit 1; }
|
||||
|
||||
find_loop_device
|
||||
sudo losetup -P "$LOOPDEV" "$target_image" || { echo "错误:设置 loop 设备失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:检查并调整文件系统大小..."
|
||||
sudo e2fsck -y -f "${LOOPDEV}p1" || { echo "错误:文件系统检查失败" >&2; exit 1; }
|
||||
sudo resize2fs "${LOOPDEV}p1" || { echo "错误:调整文件系统大小失败" >&2; exit 1; }
|
||||
|
||||
# 重新设置 LOOPDEV 为分区
|
||||
sudo losetup -d "$LOOPDEV"
|
||||
sudo losetup "$LOOPDEV" "$target_image" -o "$offset" || { echo "错误:重新设置 loop 设备失败" >&2; exit 1; }
|
||||
|
||||
echo "信息:Orange Pi Zero Rootfs 准备完成。"
|
||||
}
|
||||
|
||||
# --- 特定设备的文件配置函数 ---
|
||||
|
||||
config_cumebox2_files() {
|
||||
@@ -263,3 +332,12 @@ config_octopus_flanet_files() {
|
||||
|
||||
sudo cp "$config_file" "$ROOTFS/etc/model_database.conf" || echo "警告:复制 model_database.conf 失败"
|
||||
}
|
||||
|
||||
config_orangepizero_files() {
|
||||
echo "信息:配置 Orange Pi Zero 特定文件..."
|
||||
|
||||
# 清空 modules.conf 文件,避免加载不必要的模块
|
||||
run_in_chroot "echo '' > /etc/modules-load.d/modules.conf"
|
||||
|
||||
echo "信息:Orange Pi Zero 特定配置完成。"
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ prepare_dns_and_mirrors() {
|
||||
&& printf '%s\\n' 'nameserver 1.1.1.1' 'nameserver 1.0.0.1' > /etc/resolv.conf \\
|
||||
&& echo '信息:尝试更换镜像源...' \\
|
||||
&& bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) \\
|
||||
--source mirrors.tuna.tsinghua.edu.cn --upgrade-software false --web-protocol http || echo '警告:更换镜像源脚本执行失败,可能网络不通或脚本已更改'
|
||||
--source mirrors.ustc.edu.cn --upgrade-software false --web-protocol http || echo '警告:更换镜像源脚本执行失败,可能网络不通或脚本已更改'
|
||||
"
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ config_base_files() {
|
||||
sudo cp scripts/kvmd-gencert scripts/kvmd-bootconfig scripts/kvmd-certbot scripts/kvmd-udev-hdmiusb-check scripts/kvmd-udev-restart-pass build/scripts/kvmd-firstrun.sh "$ROOTFS/usr/bin/"
|
||||
sudo chmod +x "$ROOTFS/usr/bin/kvmd-gencert" "$ROOTFS/usr/bin/kvmd-bootconfig" "$ROOTFS/usr/bin/kvmd-certbot" "$ROOTFS/usr/bin/kvmd-udev-hdmiusb-check" "$ROOTFS/usr/bin/kvmd-udev-restart-pass" "$ROOTFS/usr/bin/kvmd-firstrun.sh"
|
||||
|
||||
# 尝试下载或使用本地 rc.local 文件
|
||||
download_rc_local "$platform_id"
|
||||
if [ -f "$SRCPATH/image/$platform_id/rc.local" ]; then
|
||||
echo "信息:复制设备特定的 rc.local 文件..."
|
||||
sudo cp "$SRCPATH/image/$platform_id/rc.local" "$ROOTFS/etc/"
|
||||
@@ -108,7 +110,7 @@ install_base_packages() {
|
||||
iptables network-manager curl kmod libmicrohttpd12 libjansson4 libssl3 \\
|
||||
libsofia-sip-ua0 libglib2.0-0 libopus0 libogg0 libcurl4 libconfig9 \\
|
||||
python3-pip net-tools libavcodec59 libavformat59 libavutil57 libswscale6 \\
|
||||
libavfilter8 libavdevice59 v4l-utils libv4l-0 && \\
|
||||
libavfilter8 libavdevice59 v4l-utils libv4l-0 nano unzip && \\
|
||||
apt clean && \\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
"
|
||||
@@ -180,9 +182,8 @@ configure_system() {
|
||||
cat /One-KVM/configs/os/udev/v2-hdmiusb-rpi4.rules > /etc/udev/rules.d/99-kvmd.rules && \\
|
||||
echo 'libcomposite' >> /etc/modules && \\
|
||||
mv /usr/local/bin/kvmd* /usr/bin/ || echo '信息:/usr/local/bin/kvmd* 未找到或移动失败,可能已在/usr/bin' && \\
|
||||
cp /One-KVM/configs/os/services/* /etc/systemd/system/ && \\
|
||||
cp -r /One-KVM/configs/os/services/* /etc/systemd/system/ && \\
|
||||
cp /One-KVM/configs/os/tmpfiles.conf /usr/lib/tmpfiles.d/ && \\
|
||||
mv /etc/kvmd/supervisord.conf /etc/supervisord.conf && \\
|
||||
chmod +x /etc/update-motd.d/* || echo '警告:chmod /etc/update-motd.d/* 失败' && \\
|
||||
echo 'kvmd ALL=(ALL) NOPASSWD: /etc/kvmd/custom_atx/gpio.sh' >> /etc/sudoers && \\
|
||||
echo 'kvmd ALL=(ALL) NOPASSWD: /etc/kvmd/custom_atx/usbrelay_hid.sh' >> /etc/sudoers && \\
|
||||
@@ -203,14 +204,16 @@ install_webterm() {
|
||||
local ttyd_arch="$arch"
|
||||
|
||||
if [ "$arch" = "armhf" ]; then
|
||||
ttyd_arch="armv7"
|
||||
ttyd_arch="armhf"
|
||||
elif [ "$arch" = "amd64" ]; then
|
||||
ttyd_arch="x86_64" # ttyd 通常用 x86_64
|
||||
ttyd_arch="x86_64"
|
||||
elif [ "$arch" = "aarch64" ]; then
|
||||
ttyd_arch="aarch64"
|
||||
fi
|
||||
|
||||
echo "信息:在 chroot 环境中下载并安装 ttyd ($ttyd_arch)..."
|
||||
run_in_chroot "
|
||||
curl -L https://gh.llkk.cc/https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.${ttyd_arch} -o /usr/bin/ttyd && \\
|
||||
curl -L https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.${ttyd_arch} -o /usr/bin/ttyd && \\
|
||||
chmod +x /usr/bin/ttyd && \\
|
||||
mkdir -p /home/kvmd-webterm && \\
|
||||
chown kvmd-webterm /home/kvmd-webterm
|
||||
@@ -245,7 +248,15 @@ apply_kvmd_tweaks() {
|
||||
|
||||
|
||||
# 根据 device_type 配置 ATX
|
||||
if [ "$device_type" = "gpio" ]; then
|
||||
if [[ "$device_type" == *"gpio-onecloud-pro"* ]]; then
|
||||
echo "信息:电源控制设备类型为 gpio,设置 ATX 为 GPIO 并配置引脚..."
|
||||
atx_setting="GPIO"
|
||||
run_in_chroot "
|
||||
sed -i 's/^ATX=.*/ATX=GPIO/' /etc/kvmd/atx.sh && \\
|
||||
sed -i 's/SHUTDOWNPIN/gpiochip0 7/g' /etc/kvmd/custom_atx/gpio.sh && \\
|
||||
sed -i 's/REBOOTPIN/gpiochip0 11/g' /etc/kvmd/custom_atx/gpio.sh
|
||||
"
|
||||
elif [[ "$device_type" == *"gpio-onecloud"* ]]; then
|
||||
echo "信息:电源控制设备类型为 gpio,设置 ATX 为 GPIO 并配置引脚..."
|
||||
atx_setting="GPIO"
|
||||
run_in_chroot "
|
||||
@@ -260,10 +271,10 @@ apply_kvmd_tweaks() {
|
||||
fi
|
||||
|
||||
# 配置视频设备
|
||||
if [ "$device_type" = "video1" ]; then
|
||||
if [[ "$device_type" == *"video1"* ]]; then
|
||||
echo "信息:视频设备类型为 video1,设置视频设备为 /dev/video1..."
|
||||
run_in_chroot "sed -i 's|/dev/video0|/dev/video1|g' /etc/kvmd/override.yaml"
|
||||
elif [ "$device_type" = "kvmd-video" ]; then
|
||||
elif [[ "$device_type" == *"video1"* ]]; then
|
||||
echo "信息:视频设备类型为 kvmd-video,设置视频设备为 /dev/kvmd-video..."
|
||||
run_in_chroot "sed -i 's|/dev/video0|/dev/kvmd-video|g' /etc/kvmd/override.yaml"
|
||||
else
|
||||
|
||||
@@ -71,8 +71,9 @@ if [ ! -f /etc/kvmd/.init_flag ]; then
|
||||
|
||||
# 设置用户名和密码
|
||||
if [ ! -z "$USERNAME" ] && [ ! -z "$PASSWORD" ]; then
|
||||
# 设置自定义用户名和密码
|
||||
if python -m kvmd.apps.htpasswd del admin \
|
||||
&& echo "$PASSWORD" | python -m kvmd.apps.htpasswd set -i "$USERNAME" \
|
||||
&& echo "$PASSWORD" | python -m kvmd.apps.htpasswd add -i "$USERNAME" \
|
||||
&& echo "$PASSWORD -> $USERNAME:$PASSWORD" > /etc/kvmd/vncpasswd \
|
||||
&& echo "$USERNAME:$PASSWORD -> $USERNAME:$PASSWORD" > /etc/kvmd/ipmipasswd; then
|
||||
log_info "用户凭据设置成功"
|
||||
@@ -80,6 +81,16 @@ if [ ! -f /etc/kvmd/.init_flag ]; then
|
||||
log_error "用户凭据设置失败"
|
||||
exit 1
|
||||
fi
|
||||
elif [ ! -z "$PASSWORD" ] && [ -z "$USERNAME" ]; then
|
||||
# 只设置密码,保持admin用户名
|
||||
if echo "$PASSWORD" | python -m kvmd.apps.htpasswd set -i "admin" \
|
||||
&& echo "$PASSWORD -> admin:$PASSWORD" > /etc/kvmd/vncpasswd \
|
||||
&& echo "admin:$PASSWORD -> admin:$PASSWORD" > /etc/kvmd/ipmipasswd; then
|
||||
log_info "admin 用户密码设置成功"
|
||||
else
|
||||
log_error "admin 用户密码设置失败"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log_warn "未设置 USERNAME 和 PASSWORD 环境变量,使用默认值(admin/admin)"
|
||||
fi
|
||||
@@ -210,8 +221,8 @@ EOF
|
||||
fi
|
||||
|
||||
if [ ! -z "$VIDEOFORMAT" ]; then
|
||||
if sed -i "s/format=mjpeg/format=$VIDFORMAT/g" /etc/kvmd/override.yaml; then
|
||||
log_info "视频输入格式已设置为 $VIDFORMAT"
|
||||
if sed -i "s/--format=mjpeg/--format=$VIDEOFORMAT/g" /etc/kvmd/override.yaml; then
|
||||
log_info "视频输入格式已设置为 $VIDEOFORMAT"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -221,6 +232,19 @@ EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
# 设置WEB端口
|
||||
if [ ! -z "$HTTPPORT" ]; then
|
||||
if sed -i "s/port: 8080/port: $HTTPPORT/g" /etc/kvmd/override.yaml; then
|
||||
log_info "HTTP 端口已设置为 $HTTPPORT"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -z "$HTTPSPORT" ]; then
|
||||
if sed -i "s/port: 4430/port: $HTTPSPORT/g" /etc/kvmd/override.yaml; then
|
||||
log_info "HTTPS 端口已设置为 $HTTPSPORT"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
touch /etc/kvmd/.init_flag
|
||||
log_info "初始化配置完成"
|
||||
|
||||
3
build/platform/onecloud-pro
Normal file
3
build/platform/onecloud-pro
Normal file
@@ -0,0 +1,3 @@
|
||||
PIKVM_MODEL=v2_model
|
||||
PIKVM_VIDEO=usb_video
|
||||
PIKVM_BOARD=onecloud-pro
|
||||
3
build/platform/orangepi-zero
Normal file
3
build/platform/orangepi-zero
Normal file
@@ -0,0 +1,3 @@
|
||||
PIKVM_MODEL=v2_model
|
||||
PIKVM_VIDEO=usb_video
|
||||
PIKVM_BOARD=orangepi-zero
|
||||
@@ -20,6 +20,7 @@
|
||||
# #
|
||||
# ========================================================================== #
|
||||
|
||||
ATX=USBRELAY_HID
|
||||
echo $ATX
|
||||
case $ATX in
|
||||
GPIO)
|
||||
|
||||
@@ -4,3 +4,4 @@ KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", PROGRAM="/usr/bin/kvmd-udev-hdm
|
||||
KERNEL=="hidg0", GROUP="kvmd", SYMLINK+="kvmd-hid-keyboard"
|
||||
KERNEL=="hidg1", GROUP="kvmd", SYMLINK+="kvmd-hid-mouse"
|
||||
KERNEL=="hidg2", GROUP="kvmd", SYMLINK+="kvmd-hid-mouse-alt"
|
||||
KERNEL=="ttyUSB0", GROUP="kvmd", SYMLINK+="kvmd-hid"
|
||||
|
||||
@@ -719,9 +719,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="hidden" id="msd-uploading-sub">
|
||||
<hr>
|
||||
</div>
|
||||
<div class="hidden" id="msd-uploading-sub">
|
||||
<table class="kv">
|
||||
<tr>
|
||||
|
||||
@@ -47,7 +47,7 @@ li.right.feature-disabled#msd-dropdown
|
||||
{title: "Flash", value: "0"},
|
||||
]) Drive #[a(target="_blank" href="https://docs.pikvm.org/msd") mode]:
|
||||
td
|
||||
+menu_switch_td2("msd-rw-switch", false, false) Writable:
|
||||
+menu_switch_td2("msd-rw-switch", false, false, "msd-rw-switch") Writable:
|
||||
tr
|
||||
td(i18n="drive_file_display") Files:
|
||||
td
|
||||
@@ -79,8 +79,6 @@ li.right.feature-disabled#msd-dropdown
|
||||
tr.hidden#msd-new-part
|
||||
td(i18n="drive_upload_partition") Upload partition:
|
||||
td(width="100%") #[select#msd-new-part-selector]
|
||||
div(id="msd-uploading-sub" class="hidden")
|
||||
hr
|
||||
|
||||
.hidden#msd-uploading-sub
|
||||
table.kv
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
"drive_unpackage_files":"Unpackage files from image",
|
||||
"drive_image_files":"Image Files",
|
||||
"drive_normal_files":"Normal Files",
|
||||
"drive_writable":"Writable:",
|
||||
|
||||
"atx-ask-switch":"Ask click confirmation",
|
||||
"hid-recorder-loop-switch":"Infinite loop playback",
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
"drive_unpackage_files":"从镜像文件解压文件",
|
||||
"drive_image_files":"镜像文件模式",
|
||||
"drive_normal_files":"普通文件模式",
|
||||
"drive_writable":"可写:",
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -42,21 +42,35 @@ function getCookie(name)
|
||||
return ""
|
||||
}
|
||||
|
||||
var i18nLanguage = "zh";
|
||||
function detectBrowserLanguage() {
|
||||
var browserLang = navigator.language || navigator.userLanguage;
|
||||
if (browserLang.startsWith('zh')) {
|
||||
return 'zh';
|
||||
} else if (browserLang.startsWith('en')) {
|
||||
return 'en';
|
||||
} else {
|
||||
return 'zh';
|
||||
}
|
||||
}
|
||||
|
||||
var i18nLanguage = detectBrowserLanguage();
|
||||
|
||||
$(document).ready(function() {
|
||||
if (getCookie('userLanguage')) {
|
||||
if (getCookie('userLanguage')) {
|
||||
i18nLanguage = getCookie('userLanguage');
|
||||
if (i18nLanguage == "zh") {
|
||||
no = 0;
|
||||
}else if (i18nLanguage == "en") {
|
||||
no = 1;
|
||||
}
|
||||
$("#selectLanguage").each(function(){
|
||||
$(this).find("option").eq(no).prop("selected",true)
|
||||
});
|
||||
}
|
||||
|
||||
var no;
|
||||
if (i18nLanguage == "zh") {
|
||||
no = 0;
|
||||
} else if (i18nLanguage == "en") {
|
||||
no = 1;
|
||||
}
|
||||
|
||||
$("#selectLanguage").each(function(){
|
||||
$(this).find("option").eq(no).prop("selected", true);
|
||||
});
|
||||
|
||||
$("[i18n]").i18n({
|
||||
defaultLang: i18nLanguage,
|
||||
filePath: "/share/i18n/",
|
||||
|
||||
@@ -337,10 +337,10 @@ export function Msd() {
|
||||
}
|
||||
if (file) {
|
||||
let e_image = encodeURIComponent(file.name);
|
||||
__http.open("POST", `${ROOT_PREFIX}api/msd/write?prefix=${e_prefix}&image=${e_image}&remove_incomplete=1`, true);
|
||||
__http.open("POST", `${ROOT_PREFIX}api/msd/write?prefix=${prefix}&image=${e_image}&remove_incomplete=1`, true);
|
||||
} else {
|
||||
let e_url = encodeURIComponent($("msd-new-url").value);
|
||||
__http.open("POST", `${ROOT_PREFIX}api/msd/write_remote?prefix=${e_prefix}&url=${e_url}&remove_incomplete=1`, true);
|
||||
__http.open("POST", `${ROOT_PREFIX}api/msd/write_remote?prefix=${prefix}&url=${e_url}&remove_incomplete=1`, true);
|
||||
}
|
||||
__http.upload.timeout = 7 * 24 * 3600;
|
||||
__http.onreadystatechange = __uploadStateChange;
|
||||
|
||||
Reference in New Issue
Block a user