Merge branch 'main' into dev

This commit is contained in:
kdwycz
2025-09-15 20:23:56 +08:00
parent 5304a68d5d
commit ad3c02c22c
4 changed files with 176 additions and 29 deletions

View File

@@ -40,6 +40,7 @@ if ($GitHubProxy -ne '') { $ProxyDisplay = $GitHubProxy } else { $ProxyDisplay =
switch ($env:PROCESSOR_ARCHITECTURE) { switch ($env:PROCESSOR_ARCHITECTURE) {
'AMD64' { $arch = 'amd64' } 'AMD64' { $arch = 'amd64' }
'ARM64' { $arch = 'arm64' } 'ARM64' { $arch = 'arm64' }
'x86' { $arch = '386' }
Default { Log-Error "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE"; exit 1 } Default { Log-Error "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE"; exit 1 }
} }

View File

@@ -57,6 +57,13 @@ case $os_type in
Linux) Linux)
os_name="linux" os_name="linux"
;; ;;
FreeBSD)
os_name="freebsd"
;;
MINGW*|MSYS*|CYGWIN*)
os_name="windows"
target_dir="/c/komari" # Use C:\komari on Windows
;;
*) *)
log_error "Unsupported operating system: $os_type" log_error "Unsupported operating system: $os_type"
exit 1 exit 1
@@ -295,23 +302,45 @@ install_dependencies
# Install vnstat if needed for month-rotate # Install vnstat if needed for month-rotate
install_vnstat install_vnstat
# Architecture detection with platform-specific support
arch=$(uname -m) arch=$(uname -m)
case $arch in case $arch in
x86_64) x86_64)
arch="amd64" arch="amd64"
;; ;;
aarch64) aarch64|arm64)
arch="arm64" arch="arm64"
;; ;;
arm64) i386|i686)
arch="arm64" # x86 (32-bit) support
case $os_name in
freebsd|linux|windows)
arch="386"
;;
*)
log_error "32-bit x86 architecture not supported on $os_name"
exit 1
;;
esac
;;
armv7*|armv6*)
# ARM 32-bit support
case $os_name in
freebsd|linux)
arch="arm"
;;
*)
log_error "32-bit ARM architecture not supported on $os_name"
exit 1
;;
esac
;; ;;
*) *)
log_error "Unsupported architecture: $arch" log_error "Unsupported architecture: $arch on $os_name"
exit 1 exit 1
;; ;;
esac esac
log_info "Detected architecture: ${GREEN}$arch${NC}" log_info "Detected OS: ${GREEN}$os_name${NC}, Architecture: ${GREEN}$arch${NC}"
version_to_install="latest" version_to_install="latest"
if [ -n "$install_version" ]; then if [ -n "$install_version" ]; then

View File

@@ -24,7 +24,7 @@ func Ram() RamInfo {
return raminfo return raminfo
} }
raminfo.Total = v.Total raminfo.Total = v.Total
raminfo.Used = v.Used raminfo.Used = v.Total - v.Available
return raminfo return raminfo
} }

View File

@@ -11,14 +11,21 @@ import (
) )
func OSName() string { func OSName() string {
// Check if it's an Android system
if androidVersion := detectAndroid(); androidVersion != "" {
return androidVersion
}
// Check if it's a Proxmox VE
if pveVersion := detectProxmoxVE(); pveVersion != "" { if pveVersion := detectProxmoxVE(); pveVersion != "" {
return pveVersion return pveVersion
} }
// Check if it's a Synology
if synologyName := detectSynology(); synologyName != "" { if synologyName := detectSynology(); synologyName != "" {
return synologyName return synologyName
} }
file, err := os.Open("/etc/os-release") file, err := os.Open("/etc/os-release")
if err != nil { if err != nil {
return "Linux" return "Linux"
@@ -45,7 +52,7 @@ func detectSynology() string {
"/etc/synoinfo.conf", "/etc/synoinfo.conf",
"/etc.defaults/synoinfo.conf", "/etc.defaults/synoinfo.conf",
} }
for _, file := range synologyFiles { for _, file := range synologyFiles {
if info, err := os.Stat(file); err == nil && !info.IsDir() { if info, err := os.Stat(file); err == nil && !info.IsDir() {
if synologyInfo := readSynologyInfo(file); synologyInfo != "" { if synologyInfo := readSynologyInfo(file); synologyInfo != "" {
@@ -53,11 +60,11 @@ func detectSynology() string {
} }
} }
} }
if info, err := os.Stat("/usr/syno"); err == nil && info.IsDir() { if info, err := os.Stat("/usr/syno"); err == nil && info.IsDir() {
return "Synology DSM" return "Synology DSM"
} }
return "" return ""
} }
@@ -67,37 +74,37 @@ func readSynologyInfo(filename string) string {
return "" return ""
} }
defer file.Close() defer file.Close()
var unique, udcCheckState string var unique, udcCheckState string
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
for scanner.Scan() { for scanner.Scan() {
line := strings.TrimSpace(scanner.Text()) line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "unique=") { if strings.HasPrefix(line, "unique=") {
unique = strings.Trim(strings.TrimPrefix(line, "unique="), `"`) unique = strings.Trim(strings.TrimPrefix(line, "unique="), `"`)
} else if strings.HasPrefix(line, "udc_check_state=") { } else if strings.HasPrefix(line, "udc_check_state=") {
udcCheckState = strings.Trim(strings.TrimPrefix(line, "udc_check_state="), `"`) udcCheckState = strings.Trim(strings.TrimPrefix(line, "udc_check_state="), `"`)
} }
} }
if unique != "" && strings.Contains(unique, "synology_") { if unique != "" && strings.Contains(unique, "synology_") {
parts := strings.Split(unique, "_") parts := strings.Split(unique, "_")
if len(parts) >= 3 { if len(parts) >= 3 {
model := strings.ToUpper(parts[len(parts)-1]) model := strings.ToUpper(parts[len(parts)-1])
result := "Synology " + model result := "Synology " + model
if udcCheckState != "" { if udcCheckState != "" {
result += " DSM " + udcCheckState result += " DSM " + udcCheckState
} else { } else {
result += " DSM" result += " DSM"
} }
return result return result
} }
} }
return "" return ""
} }
@@ -105,21 +112,21 @@ func detectProxmoxVE() string {
if _, err := exec.LookPath("pveversion"); err != nil { if _, err := exec.LookPath("pveversion"); err != nil {
return "" return ""
} }
out, err := exec.Command("pveversion").Output() out, err := exec.Command("pveversion").Output()
if err != nil { if err != nil {
return "" return ""
} }
output := strings.TrimSpace(string(out)) output := strings.TrimSpace(string(out))
lines := strings.Split(output, "\n") lines := strings.Split(output, "\n")
var version string var version string
var codename string var codename string
for _, line := range lines { for _, line := range lines {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if strings.HasPrefix(line, "pve-manager/") { if strings.HasPrefix(line, "pve-manager/") {
parts := strings.Split(line, "/") parts := strings.Split(line, "/")
if len(parts) >= 2 { if len(parts) >= 2 {
@@ -130,9 +137,9 @@ func detectProxmoxVE() string {
version = versionPart version = versionPart
} }
} }
} }
if version != "" { if version != "" {
if file, err := os.Open("/etc/os-release"); err == nil { if file, err := os.Open("/etc/os-release"); err == nil {
defer file.Close() defer file.Close()
@@ -146,23 +153,133 @@ func detectProxmoxVE() string {
} }
} }
} }
if version != "" { if version != "" {
if codename != "" { if codename != "" {
return "Proxmox VE " + version + " (" + codename + ")" return "Proxmox VE " + version + " (" + codename + ")"
} }
return "Proxmox VE " + version return "Proxmox VE " + version
} }
return "Proxmox VE" return "Proxmox VE"
} }
// detectAndroid detects if the system is Android and returns detailed information
func detectAndroid() string {
// 1. Try to get Android version info using the getprop command
cmdGetprop := exec.Command("getprop", "ro.build.version.release")
version, err := cmdGetprop.Output()
if err == nil && len(version) > 0 {
versionStr := strings.TrimSpace(string(version))
// Get device model
cmdGetModel := exec.Command("getprop", "ro.product.model")
model, err2 := cmdGetModel.Output()
modelStr := strings.TrimSpace(string(model))
// Get manufacturer information
cmdGetBrand := exec.Command("getprop", "ro.product.brand")
brand, err3 := cmdGetBrand.Output()
brandStr := strings.TrimSpace(string(brand))
result := "Android " + versionStr
// Add brand and model information (if available)
if err2 == nil && modelStr != "" {
if err3 == nil && brandStr != "" && brandStr != modelStr {
result += " (" + brandStr + " " + modelStr + ")"
} else {
result += " (" + modelStr + ")"
}
}
return result
}
// 2. Try to check Android system build.prop file
if _, err := os.Stat("/system/build.prop"); err == nil {
return readAndroidBuildProp()
}
// 3. Check for typical Android directory structure
if isAndroidSystem() {
return "Android"
}
return ""
}
// readAndroidBuildProp reads Android version information from build.prop file
func readAndroidBuildProp() string {
file, err := os.Open("/system/build.prop")
if err != nil {
return "Android"
}
defer file.Close()
var version, model, brand string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "ro.build.version.release=") {
version = strings.TrimPrefix(line, "ro.build.version.release=")
} else if strings.HasPrefix(line, "ro.product.model=") {
model = strings.TrimPrefix(line, "ro.product.model=")
} else if strings.HasPrefix(line, "ro.product.brand=") {
brand = strings.TrimPrefix(line, "ro.product.brand=")
}
// If all information has been collected, we can exit early
if version != "" && model != "" && brand != "" {
break
}
}
if version != "" {
result := "Android " + version
if model != "" {
if brand != "" && brand != model {
result += " (" + brand + " " + model + ")"
} else {
result += " (" + model + ")"
}
}
return result
}
return "Android"
}
// isAndroidSystem determines if the system is Android by checking typical directory structure
func isAndroidSystem() bool {
androidDirs := []string{
"/system/app",
"/system/priv-app",
"/data/app",
"/sdcard",
}
dirCount := 0
for _, dir := range androidDirs {
if info, err := os.Stat(dir); err == nil && info.IsDir() {
dirCount++
}
}
// Consider it an Android system only if at least 2 directories exist
return dirCount >= 2
}
// KernelVersion returns the kernel version on Linux systems // KernelVersion returns the kernel version on Linux systems
func KernelVersion() string { func KernelVersion() string {
out, err := exec.Command("uname", "-r").Output() out, err := exec.Command("uname", "-r").Output()
if err != nil { if err != nil {
return "Unknown" return "Unknown"
} }
return strings.TrimSpace(string(out)) return strings.TrimSpace(string(out))
} }