package containers import ( "debug/elf" "fmt" "github.com/coroot/coroot-node-agent/flags" . "github.com/coroot/coroot-node-agent/utils/modelse" klog "github.com/sirupsen/logrus" "os" "os/exec" "regexp" "runtime" "strings" ) var libjvmRegex = regexp.MustCompile(`.*/libjvm\.so`) func GetExeType(pid uint32, rootfs string) CodeType { mapsFilePath := fmt.Sprintf("%sproc/%d/maps", "/", pid) data, err := os.ReadFile(mapsFilePath) if err != nil { klog.WithError(err).Errorf("Failed to read %s: %s", mapsFilePath) return CodeTypeUnknown } content := string(data) if libjvmRegex.MatchString(content) { //fmt.Println("is java process") if isJavaAotProcess(pid, rootfs) { //fmt.Println("is javaAot process") return CodeTypeJavaAot } return CodeTypeJava } else if isJavaAotProcess(pid, rootfs) { //fmt.Println("is javaAot process") return CodeTypeJavaAot } else if isGoProcess(pid, rootfs) { //fmt.Println("is go process") return CodeTypeGo } else if isNetCoreProcess(pid, rootfs) { // fmt.Println("is netcore process") return CodeTypeNetCoreAot } return CodeTypeUnknown } // isJavaAotProcess checks if the process with the given PID is a GraalVM native image func isJavaAotProcess(pid uint32, rootfs string) bool { // Get the executable path for the given PID exePath, err := os.Readlink(fmt.Sprintf("%sproc/%d/exe", "/", pid)) if err != nil { //fmt.Printf("Error reading executable path for PID %d: %v\n", pid, err) klog.WithError(err).Errorf("isJavaAotProcess,failed to reading executable path for PID [%d]", pid) return false } // Read the content of the executable file pathPrefix := rootfs if pathPrefix == "" && *flags.RunInContainer { pathPrefix = *flags.HostDirPathPrefix } content, err := os.ReadFile(fmt.Sprintf("%s%s", pathPrefix, exePath)) if err != nil { if _, err = os.Stat(exePath); err == nil { content, err = os.ReadFile(exePath) if err != nil { klog.WithError(err).Errorf("isJavaAotProcess,failed to reading executable file local for PID [%d]", pid) return false } } else { klog.WithError(err).Errorf("isJavaAotProcess,failed to reading executable file for PID [%d]", pid) return false } } // Check if the file contains the "graal_attach_thread" string if strings.Contains(string(content), "graal_attach_thread") { return true } return false } func isNetCoreProcess(pid uint32, rootfs string) bool { path, err := getProcessPath(pid) if err != nil { //fmt.Printf("无法获取进程路径:%s\n", err) klog.WithError(err).Errorf("isNetCoreProcess,failed to open as elf binary path for PID [%d]", pid) return false } pathPrefix := rootfs if pathPrefix == "" && *flags.RunInContainer { pathPrefix = *flags.HostDirPathPrefix } ef, err := elf.Open(pathPrefix + path) if err != nil { if _, err = os.Stat(path); err == nil { ef, err = elf.Open(path) if err != nil { klog.WithError(err).Errorf("isNetCoreProcess,failed to open as elf binary file local for PID [%d]", pid) return false } } else { klog.WithError(err).Errorf("isNetCoreProcess,failed to open as elf binary file for PID [%d]", pid) return false } } defer ef.Close() __managedcode := ef.Section("__managedcode") if __managedcode != nil { fmt.Println("is a netcore process") return true } return false } func isGoProcess(pid uint32, rootfs string) bool { path, err := getProcessPath(pid) if err != nil { klog.WithError(err).Errorf("isGoProcess,failed to open as elf binary path for PID [%d]", pid) return false } pathPrefix := rootfs if pathPrefix == "" && *flags.RunInContainer { pathPrefix = *flags.HostDirPathPrefix } ef, err := elf.Open(pathPrefix + path) if err != nil { if _, err = os.Stat(path); err == nil { ef, err = elf.Open(path) if err != nil { klog.WithError(err).Errorf("isGoProcess,failed to open as elf binary file local for PID [%d]", pid) return false } } else { klog.WithError(err).Errorf("isGoProcess,failed to open as elf binary file for PID [%d]", pid) return false } } defer ef.Close() gopclntabSection := ef.Section(".gopclntab") if gopclntabSection != nil { //fmt.Println("is a go process") return true } return false } func getProcessPath(pid uint32) (string, error) { switch runtime.GOOS { case "linux": return getLinuxProcessPath(pid) default: return "", fmt.Errorf("不支持的操作系统:%s", runtime.GOOS) } } func getLinuxProcessPath(pid uint32) (string, error) { procPath := fmt.Sprintf("/proc/%d/exe", pid) path, err := os.Readlink(procPath) if err != nil { return "", err } return path, nil } func executeCommand(name string, args ...string) (string, error) { cmd := exec.Command(name, args...) out, err := cmd.Output() if err != nil { return "", err } return string(out), nil }