util.go 3.1 KB

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