summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author林鑫 <[email protected]>2024-08-14 09:27:16 +0000
committer林鑫 <[email protected]>2024-08-14 09:27:16 +0000
commit0f57bb2439d8fdf63665ee9ab5037ac06a24dea8 (patch)
treea9a12a748c17468bb1956530002a900ee26b8b35
parentac91fe086983e280b6a1f5b3c822d1e78f0fb442 (diff)
✨ feat:add feature:store excutable file of coredump
-rw-r--r--.vscode/settings.json4
-rw-r--r--coredump-handler/coredump-handler.go100
-rw-r--r--coredump-handler/coredump-handler_test.go6
-rw-r--r--coredump-tool/coredump-tool.go278
-rw-r--r--types/types.go1
5 files changed, 252 insertions, 137 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..043dcf4
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,4 @@
+{
+ "DevChat.PythonForChat": "c:\\Users\\10126\\.vscode\\extensions\\merico.devchat-0.1.47\\tools\\python-3.11.6-embed-amd64\\python.exe",
+ "DevChat.PythonForCommands": "C:\\Users\\10126\\.chat\\mamba\\envs\\devchat-commands\\python.exe"
+} \ No newline at end of file
diff --git a/coredump-handler/coredump-handler.go b/coredump-handler/coredump-handler.go
index bbf072e..4711e72 100644
--- a/coredump-handler/coredump-handler.go
+++ b/coredump-handler/coredump-handler.go
@@ -8,6 +8,7 @@ import "C"
import (
"archive/zip"
+ "bufio"
"context"
"coredump-tools/config"
"coredump-tools/types"
@@ -253,6 +254,103 @@ func compress(config types.Coredump_config) error {
return nil
}
+func getLibrariesFromMaps(mapsFile string) ([]string, error) {
+ file, err := os.Open(mapsFile)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ libSet := make(map[string]struct{})
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Fields(line)
+ if len(parts) > 5 && !strings.Contains(parts[5], "[") && strings.Contains(parts[1], "x") {
+ libSet[parts[5]] = struct{}{}
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+
+ var libs []string
+ for lib := range libSet {
+ libs = append(libs, lib)
+ }
+
+ return libs, nil
+}
+
+func addFileToZip(zipWriter *zip.Writer, filename string, pid string, pipe_config types.Pipeconfig) error {
+ libabspath := fmt.Sprintf("/proc/%s/root%s", pid, filename)
+ fileToZip, err := os.Open(libabspath)
+ if err != nil {
+ return err
+ }
+ defer fileToZip.Close()
+
+ info, err := fileToZip.Stat()
+ if err != nil {
+ return err
+ }
+
+ header, err := zip.FileInfoHeader(info)
+ if err != nil {
+ return err
+ }
+ header.Name = filename
+ header.Method = zip.Deflate
+
+ writer, err := zipWriter.CreateHeader(header)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(writer, fileToZip)
+ if err != nil {
+ return err
+ }
+ flag, _, err := isDiskSufficient(pipe_config)
+ if err != nil {
+ journal.Print(journal.PriErr, "Can't judge disk's space is sufficient or not. "+err.Error())
+ return err
+ }
+ if !flag {
+ return errors.New("Disk space exceeds limit when writing coredump!")
+ }
+ return nil
+}
+
+func writelibfile(pid string, pipe_config types.Pipeconfig) error {
+ mapsFile := fmt.Sprintf("/proc/%s/maps", pid)
+ libs, err := getLibrariesFromMaps(mapsFile)
+ if err != nil {
+ return err
+ }
+ // for _, lib := range libs {
+ // journal.Print(journal.PriDebug,lib)
+ // }
+ // journal.Print(journal.PriDebug,"lib's num:", len(libs))
+ filePath := fmt.Sprintf("%s/Executable_file.gz", pipe_config.Storage)
+ zipFile, err := os.Create(filePath)
+ if err != nil {
+ return err
+ }
+ defer zipFile.Close()
+
+ zipWriter := zip.NewWriter(zipFile)
+ defer zipWriter.Close()
+
+ for _, file := range libs {
+ addFileToZip(zipWriter, file, pid, pipe_config)
+ }
+
+ journal.Print(journal.PriInfo, "Tar file created successfully")
+ return nil
+}
+
func init() {
flag.StringVar(&coredump_config.Initial_ns_pid, "P", "", "initial ns pid")
flag.StringVar(&coredump_config.Process_ns_pid, "p", "", "process ns pid")
@@ -367,6 +465,8 @@ func start() {
}
coredump_config.Storage = fmt.Sprintf("%s/%s_%s_%d.coredump.zip", pipe_config.Storage, coredump_config.Initial_ns_pid, coredump_config.Process_ns_pid, coredump_config.Timestamp)
}
+ writelibfile(coredump_config.Initial_ns_pid, pipe_config)
+ coredump_config.Executable_file = fmt.Sprintf("%s/Executable_file.gz", pipe_config.Storage)
//write coredump info
err = writeCoreConfig(coredump_config)
if err != nil {
diff --git a/coredump-handler/coredump-handler_test.go b/coredump-handler/coredump-handler_test.go
index 70dea3d..b82989b 100644
--- a/coredump-handler/coredump-handler_test.go
+++ b/coredump-handler/coredump-handler_test.go
@@ -45,7 +45,7 @@ func TestIsDiskSufficient(t *testing.T) {
pipe_config := types.Pipeconfig{
Total_file_mem_limit: "50%",
}
- res, err := isDiskSufficient(pipe_config)
+ res, _, err := isDiskSufficient(pipe_config)
if err != nil || !res {
t.Errorf("isDiskSufficient() error = %v; want res = true", err)
}
@@ -76,8 +76,8 @@ func TestGetContainerId(t *testing.T) {
}
func TestGetImageId(t *testing.T) {
- image_id, err := getImageName("1234567890abcdef", "/var/run/containerd.sock")
- if err != nil || len(image_id) == 0 {
+ image_id, pod_name, err := getContainerInfo("1234567890abcdef", "/var/run/containerd.sock")
+ if err != nil || len(image_id) == 0 || len(pod_name) == 0 {
t.Errorf("getImageId() error = %v; want image_id != \"\"", err)
}
}
diff --git a/coredump-tool/coredump-tool.go b/coredump-tool/coredump-tool.go
index b659d1e..45dda30 100644
--- a/coredump-tool/coredump-tool.go
+++ b/coredump-tool/coredump-tool.go
@@ -1,6 +1,7 @@
package main
import (
+ "bufio"
"bytes"
"context"
"coredump-tools/types"
@@ -123,22 +124,6 @@ func list(pid string) {
}
func info(pid string) {
- table := simpletable.New()
-
- table.Header = &simpletable.Header{
- Cells: []*simpletable.Cell{
- {Text: "PID"},
- {Text: "UID"},
- {Text: "GID"},
- {Text: "SIG"},
- {Text: "EXE"},
- {Text: "POD"},
- {Text: "IMAGE"},
- {Text: "HOSTNAME"},
- {Text: "STORAGE"},
- {Text: "TIMESTAMP"},
- },
- }
total := 0
// output the config's info
for _, c := range configs {
@@ -146,25 +131,46 @@ func info(pid string) {
continue
}
coreTime := time.Unix(c.Timestamp, 0).Format("2006-01-02 15:04:05")
- r := []*simpletable.Cell{
- {Text: c.Initial_ns_pid},
- {Text: c.UID},
- {Text: c.GID},
- {Text: strconv.Itoa(c.Signal)},
- {Text: c.Process_exe_path},
- {Text: c.Pod_name},
- {Text: c.Image_name},
- {Text: c.Hostname},
- {Text: c.Storage},
- {Text: coreTime},
- }
- table.Body.Cells = append(table.Body.Cells, r)
+ fmt.Println("PID: " + c.Initial_ns_pid)
+ fmt.Println("UID: " + c.UID)
+ fmt.Println("GID: " + c.GID)
+ fmt.Println("SIG: " + strconv.Itoa(c.Signal))
+ fmt.Println("EXE: " + c.Process_exe_path)
+ fmt.Println("POD: " + c.Pod_name)
+ fmt.Println("IMAGE: " + c.Image_name)
+ fmt.Println("HOSTNAME: " + c.Hostname)
+ fmt.Println("STORAGE: " + c.Storage)
+ fmt.Println("TIMESTAMP: " + coreTime)
+ fmt.Println()
+ fmt.Println()
total += 1
}
- fmt.Println(table.String())
fmt.Println("Total", total, "coredumps")
}
+func getImageVersion() (string, error) {
+ file, err := os.Open("/etc/os-release")
+ if err != nil {
+ return "", err
+ }
+ defer file.Close()
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "VERSION=") {
+ version := strings.TrimPrefix(line, "VERSION=")
+ version = strings.Trim(version, "\"")
+ imageVersion := strings.Split(version, " ")
+ fmt.Println("imageVersion:", imageVersion[0])
+ if len(imageVersion[0]) > 0 {
+ return imageVersion[0], nil
+ }
+ break
+ }
+ }
+ return "", errors.New("get empty version info")
+}
+
func debug(config types.Coredump_config, command, prestartPath string) error {
if strings.HasSuffix(config.Storage, ".minidump") {
corefile := strings.Replace(config.Storage, ".minidump", ".coredump", -1)
@@ -178,43 +184,33 @@ func debug(config types.Coredump_config, command, prestartPath string) error {
config.Storage = corefile
defer os.Remove(corefile)
}
- if config.Image_name != "NULL" {
- kubeconfig := os.Getenv("KUBECONFIG")
- if kubeconfig == "" {
- kubeconfig = os.Getenv("HOME") + "/.kube/config"
- }
+ kubeconfig := os.Getenv("KUBECONFIG")
+ if kubeconfig == "" {
+ kubeconfig = os.Getenv("HOME") + "/.kube/config"
+ }
- // Creates the kubernetes client using the specified kubeconfig
- conf, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
- if err != nil {
- return err
- }
+ // Creates the kubernetes client using the specified kubeconfig
+ conf, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
+ if err != nil {
+ return err
+ }
- clientset, err := kubernetes.NewForConfig(conf)
- if err != nil {
- return err
- }
- podName, err := debugInpod(conf, clientset, config, command, prestartPath)
- if err != nil {
- fmt.Println(err)
- }
- // Delete the Pod
+ clientset, err := kubernetes.NewForConfig(conf)
+ if err != nil {
+ return err
+ }
+ podName, err := debugInpod(conf, clientset, config, command, prestartPath)
+ if err != nil {
+ fmt.Println(err)
+ }
+ // Delete the Pod
+ if podName != "" {
fmt.Printf("Deleting Pod %q...\n", podName)
err = clientset.CoreV1().Pods("default").Delete(context.Background(), podName, metav1.DeleteOptions{})
if err != nil {
return err
}
fmt.Printf("Deleted Pod %q.\n", podName)
- return nil
- } else { // using gdb to debug the coredump file
- cmd := exec.Command("gdb", config.Process_exe_path, config.Storage, "-cd", filepath.Dir(config.Process_exe_path))
- cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- fmt.Println(cmd.String())
- if err := cmd.Run(); err != nil {
- return err
- }
}
return nil
}
@@ -224,81 +220,71 @@ func debugInpod(conf *rest.Config, clientset *kubernetes.Clientset, config types
fmt.Println(id.String())
podName := fmt.Sprintf("coredump-debug-%s", id.String())
containerName := "debug"
- pod := &v1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: podName,
- Namespace: "default",
+ imageversion, err := getImageVersion()
+ if err != nil {
+ return "", err
+ }
+ image := fmt.Sprintln("registry.gdnt-cloud.website/tsg-init:", imageversion)
+ volumeMounts := []v1.VolumeMount{
+ {
+ Name: "host-dir",
+ MountPath: "/host",
},
- Spec: v1.PodSpec{
- Containers: []v1.Container{
- {
- Name: "debug",
- Image: config.Image_name,
- ImagePullPolicy: "IfNotPresent",
- Command: []string{
- "tail",
- "-f",
- },
- VolumeMounts: []v1.VolumeMount{
- {
- Name: "host-dir",
- MountPath: "/host",
- },
- {
- Name: "lib-debuginfo-dir",
- MountPath: "/usr/lib/debug",
- },
- {
- Name: "src-debuginfo-dir",
- MountPath: "/usr/src/debug",
- },
- {
- Name: "mrzcpd",
- MountPath: "/opt/tsg/mrzcpd",
- },
- },
- SecurityContext: &v1.SecurityContext{
- Privileged: &[]bool{true}[0],
- },
+ {
+ Name: "lib-debuginfo-dir",
+ MountPath: "/usr/lib/debug",
+ },
+ {
+ Name: "src-debuginfo-dir",
+ MountPath: "/usr/src/debug",
+ },
+ {
+ Name: "mrzcpd",
+ MountPath: "/opt/tsg/mrzcpd",
+ },
+ }
+ volumes := []v1.Volume{
+ {
+ Name: "host-dir",
+ VolumeSource: v1.VolumeSource{
+ HostPath: &v1.HostPathVolumeSource{
+ Path: "/",
},
},
- Volumes: []v1.Volume{
- {
- Name: "host-dir",
- VolumeSource: v1.VolumeSource{
- HostPath: &v1.HostPathVolumeSource{
- Path: "/",
- },
- },
- },
- {
- Name: "lib-debuginfo-dir",
- VolumeSource: v1.VolumeSource{
- HostPath: &v1.HostPathVolumeSource{
- Path: "/usr/lib/debug",
- },
- },
+ },
+ {
+ Name: "lib-debuginfo-dir",
+ VolumeSource: v1.VolumeSource{
+ HostPath: &v1.HostPathVolumeSource{
+ Path: "/usr/lib/debug",
},
- {
- Name: "src-debuginfo-dir",
- VolumeSource: v1.VolumeSource{
- HostPath: &v1.HostPathVolumeSource{
- Path: "/usr/src/debug",
- },
- },
+ },
+ },
+ {
+ Name: "src-debuginfo-dir",
+ VolumeSource: v1.VolumeSource{
+ HostPath: &v1.HostPathVolumeSource{
+ Path: "/usr/src/debug",
},
- {
- Name: "mrzcpd",
- VolumeSource: v1.VolumeSource{
- HostPath: &v1.HostPathVolumeSource{
- Path: "/opt/tsg/mrzcpd",
- },
- },
+ },
+ },
+ {
+ Name: "mrzcpd",
+ VolumeSource: v1.VolumeSource{
+ HostPath: &v1.HostPathVolumeSource{
+ Path: "/opt/tsg/mrzcpd",
},
},
- RestartPolicy: v1.RestartPolicyNever,
},
}
+ var containerCommands []string
+ var containerCommand string
+ if _, err := os.Stat(config.Executable_file); err != nil {
+ fmt.Println(err)
+ containerCommand = "tail -f"
+ } else {
+ containerCommand = fmt.Sprintf("unzip -o /host%s ; tail -f", config.Executable_file)
+ }
if prestartPath != "" {
prestartVolumeMount := v1.VolumeMount{
Name: "prestart-dir",
@@ -312,20 +298,48 @@ func debugInpod(conf *rest.Config, clientset *kubernetes.Clientset, config types
},
},
}
- pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, prestartVolumeMount)
- pod.Spec.Volumes = append(pod.Spec.Volumes, prestartVolume)
- pod.Spec.Containers[0].Command = []string{
+ volumeMounts = append(volumeMounts, prestartVolumeMount)
+ volumes = append(volumes, prestartVolume)
+ containerCommands = []string{
"sh",
"-c",
- "chmod +x /prestart.sh && /prestart.sh && tail -f",
+ "chmod +x /prestart.sh && /prestart.sh && " + containerCommand,
+ }
+ } else {
+ containerCommands = []string{
+ "sh",
+ "-c",
+ containerCommand,
}
}
+ pod := &v1.Pod{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: podName,
+ Namespace: "default",
+ },
+ Spec: v1.PodSpec{
+ Containers: []v1.Container{
+ {
+ Name: "debug",
+ Image: image,
+ ImagePullPolicy: "IfNotPresent",
+ Command: containerCommands,
+ VolumeMounts: volumeMounts,
+ SecurityContext: &v1.SecurityContext{
+ Privileged: &[]bool{true}[0],
+ },
+ },
+ },
+ Volumes: volumes,
+ RestartPolicy: v1.RestartPolicyNever,
+ },
+ }
// Create the Pod
fmt.Println("Creating Pod...")
fmt.Printf("Creating Pod %q...\n", podName)
result, err := clientset.CoreV1().Pods("default").Create(context.Background(), pod, metav1.CreateOptions{})
if err != nil {
- return podName, err
+ return "", err
}
fmt.Printf("Created Pod %q.\n", result.GetObjectMeta().GetName())
@@ -496,10 +510,6 @@ func command_init() cli.App {
WalkDirectory(dirPath)
for _, config := range configs {
if strings.Compare(config.Initial_ns_pid, pid) == 0 || pid == "" {
- if prestartPath != "" && config.Image_name == "NULL" {
- fmt.Println("Coredump is not generate in Pod.Prestart just use in Pod's coredump debug!")
- return nil
- }
err := debug(config, command, prestartPath)
if err != nil {
fmt.Println(err)
diff --git a/types/types.go b/types/types.go
index c2e11f9..9d77f9e 100644
--- a/types/types.go
+++ b/types/types.go
@@ -27,6 +27,7 @@ type Coredump_config struct {
Signal int
Hostname string
Storage string
+ Executable_file string
}
type Coredump_cli_table struct {
PID string