diff --git a/common/sys_log.go b/common/sys_log.go index 478015f07..c3e736daa 100644 --- a/common/sys_log.go +++ b/common/sys_log.go @@ -2,9 +2,10 @@ package common import ( "fmt" - "github.com/gin-gonic/gin" "os" "time" + + "github.com/gin-gonic/gin" ) func SysLog(s string) { @@ -22,3 +23,35 @@ func FatalLog(v ...any) { _, _ = fmt.Fprintf(gin.DefaultErrorWriter, "[FATAL] %v | %v \n", t.Format("2006/01/02 - 15:04:05"), v) os.Exit(1) } + +func LogStartupSuccess(startTime time.Time, port string) { + + duration := time.Since(startTime) + durationMs := duration.Milliseconds() + + // Get network IPs + networkIps := GetNetworkIps() + + // Print blank line for spacing + fmt.Fprintf(gin.DefaultWriter, "\n") + + // Print the main success message + fmt.Fprintf(gin.DefaultWriter, " \033[32m%s %s\033[0m ready in %d ms\n", SystemName, Version, durationMs) + fmt.Fprintf(gin.DefaultWriter, "\n") + + // Skip fancy startup message in container environments + if IsRunningInContainer() { + return + } + + // Print local URL + fmt.Fprintf(gin.DefaultWriter, " ➜ \033[1mLocal:\033[0m http://localhost:%s/\n", port) + + // Print network URLs + for _, ip := range networkIps { + fmt.Fprintf(gin.DefaultWriter, " ➜ \033[1mNetwork:\033[0m http://%s:%s/\n", ip, port) + } + + // Print blank line for spacing + fmt.Fprintf(gin.DefaultWriter, "\n") +} diff --git a/common/utils.go b/common/utils.go index 883abfd1a..21f72ec6a 100644 --- a/common/utils.go +++ b/common/utils.go @@ -68,6 +68,78 @@ func GetIp() (ip string) { return } +func GetNetworkIps() []string { + var networkIps []string + ips, err := net.InterfaceAddrs() + if err != nil { + log.Println(err) + return networkIps + } + + for _, a := range ips { + if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { + if ipNet.IP.To4() != nil { + ip := ipNet.IP.String() + // Include common private network ranges + if strings.HasPrefix(ip, "10.") || + strings.HasPrefix(ip, "172.") || + strings.HasPrefix(ip, "192.168.") { + networkIps = append(networkIps, ip) + } + } + } + } + return networkIps +} + +// IsRunningInContainer detects if the application is running inside a container +func IsRunningInContainer() bool { + // Method 1: Check for .dockerenv file (Docker containers) + if _, err := os.Stat("/.dockerenv"); err == nil { + return true + } + + // Method 2: Check cgroup for container indicators + if data, err := os.ReadFile("/proc/1/cgroup"); err == nil { + content := string(data) + if strings.Contains(content, "docker") || + strings.Contains(content, "containerd") || + strings.Contains(content, "kubepods") || + strings.Contains(content, "/lxc/") { + return true + } + } + + // Method 3: Check environment variables commonly set by container runtimes + containerEnvVars := []string{ + "KUBERNETES_SERVICE_HOST", + "DOCKER_CONTAINER", + "container", + } + + for _, envVar := range containerEnvVars { + if os.Getenv(envVar) != "" { + return true + } + } + + // Method 4: Check if init process is not the traditional init + if data, err := os.ReadFile("/proc/1/comm"); err == nil { + comm := strings.TrimSpace(string(data)) + // In containers, process 1 is often not "init" or "systemd" + if comm != "init" && comm != "systemd" { + // Additional check: if it's a common container entrypoint + if strings.Contains(comm, "docker") || + strings.Contains(comm, "containerd") || + strings.Contains(comm, "runc") { + return true + } + } + } + + return false +} + var sizeKB = 1024 var sizeMB = sizeKB * 1024 var sizeGB = sizeMB * 1024 diff --git a/main.go b/main.go index 0caf53617..b1421f9ef 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "one-api/setting/ratio_setting" "os" "strconv" + "time" "github.com/bytedance/gopkg/util/gopool" "github.com/gin-contrib/sessions" @@ -33,6 +34,7 @@ var buildFS embed.FS var indexPage []byte func main() { + startTime := time.Now() err := InitResources() if err != nil { @@ -150,6 +152,10 @@ func main() { if port == "" { port = strconv.Itoa(*common.Port) } + + // Log startup success message + common.LogStartupSuccess(startTime, port) + err = server.Run(":" + port) if err != nil { common.FatalLog("failed to start HTTP server: " + err.Error()) @@ -204,4 +210,4 @@ func InitResources() error { return err } return nil -} \ No newline at end of file +}