| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- 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
- }
|