util.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package containers
  2. import (
  3. "debug/elf"
  4. "fmt"
  5. . "github.com/coroot/coroot-node-agent/utils/modelse"
  6. klog "github.com/sirupsen/logrus"
  7. "io/ioutil"
  8. "os"
  9. "os/exec"
  10. "regexp"
  11. "runtime"
  12. "strings"
  13. )
  14. var libjvmRegex = regexp.MustCompile(`.*/libjvm\.so`)
  15. func GetExeType(pid uint32) CodeType {
  16. mapsFilePath := fmt.Sprintf("/proc/%d/maps", pid)
  17. data, err := os.ReadFile(mapsFilePath)
  18. if err != nil {
  19. klog.WithError(err).Errorf("Failed to read %s: %s", mapsFilePath)
  20. return CodeTypeUnknown
  21. }
  22. content := string(data)
  23. if libjvmRegex.MatchString(content) {
  24. //fmt.Println("is java process")
  25. if isJavaAotProcess(pid) {
  26. //fmt.Println("is javaAot process")
  27. return CodeTypeJavaAot
  28. }
  29. return CodeTypeJava
  30. } else if isJavaAotProcess(pid) {
  31. //fmt.Println("is javaAot process")
  32. return CodeTypeJavaAot
  33. } else if isGoProcess(pid) {
  34. //fmt.Println("is go process")
  35. return CodeTypeGo
  36. } else if isNetCoreProcess(pid) {
  37. // fmt.Println("is netcore process")
  38. return CodeTypeNetCoreAot
  39. }
  40. return CodeTypeUnknown
  41. }
  42. // isJavaAotProcess checks if the process with the given PID is a GraalVM native image
  43. func isJavaAotProcess(pid uint32) bool {
  44. // Get the executable path for the given PID
  45. exePath, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
  46. if err != nil {
  47. fmt.Printf("Error reading executable path for PID %d: %v\n", pid, err)
  48. return false
  49. }
  50. // Read the content of the executable file
  51. content, err := ioutil.ReadFile(exePath)
  52. if err != nil {
  53. fmt.Printf("Error reading executable file for PID %d: %v\n", pid, err)
  54. return false
  55. }
  56. // Check if the file contains the "graal_attach_thread" string
  57. if strings.Contains(string(content), "graal_attach_thread") {
  58. return true
  59. }
  60. return false
  61. }
  62. func isNetCoreProcess(pid uint32) bool {
  63. path, err := getProcessPath(pid)
  64. if err != nil {
  65. fmt.Printf("无法获取进程路径:%s\n", err)
  66. return false
  67. }
  68. ef, err := elf.Open(path)
  69. if err != nil {
  70. fmt.Println("failed to open as elf binary", err)
  71. return false
  72. }
  73. defer ef.Close()
  74. __managedcode := ef.Section("__managedcode")
  75. if __managedcode != nil {
  76. fmt.Println("is a netcore process")
  77. return true
  78. }
  79. return false
  80. }
  81. func isGoProcess(pid uint32) bool {
  82. path, err := getProcessPath(pid)
  83. if err != nil {
  84. fmt.Printf("无法获取进程路径:%s\n", err)
  85. return false
  86. }
  87. ef, err := elf.Open(path)
  88. if err != nil {
  89. fmt.Println("failed to open as elf binary", err)
  90. return false
  91. }
  92. defer ef.Close()
  93. gopclntabSection := ef.Section(".gopclntab")
  94. if gopclntabSection != nil {
  95. //fmt.Println("is a go process")
  96. return true
  97. }
  98. return false
  99. }
  100. func getProcessPath(pid uint32) (string, error) {
  101. switch runtime.GOOS {
  102. case "linux":
  103. return getLinuxProcessPath(pid)
  104. default:
  105. return "", fmt.Errorf("不支持的操作系统:%s", runtime.GOOS)
  106. }
  107. }
  108. func getLinuxProcessPath(pid uint32) (string, error) {
  109. procPath := fmt.Sprintf("/proc/%d/exe", pid)
  110. path, err := os.Readlink(procPath)
  111. if err != nil {
  112. return "", err
  113. }
  114. return path, nil
  115. }
  116. func executeCommand(name string, args ...string) (string, error) {
  117. cmd := exec.Command(name, args...)
  118. out, err := cmd.Output()
  119. if err != nil {
  120. return "", err
  121. }
  122. return string(out), nil
  123. }