2016-12-09 2 views
1

Was wäre eine effektive Möglichkeit, einen Prozess mit Go-Code zu töten, wenn Sie nur den Prozessnamen kennen? Ich sehe einige das os Paket bereitgestellten Funktionen wie:Golang - Kill Prozess nach Name

func FindProcess(pid int) (*Process, error) 
func (p *Process) Kill() error 
func (p *Process) Signal(sig Signal) error 

Gibt es eine gute/übliche Praxis, die pid, ohne dass Befehle ausführen zu bekommen und dann die Ausgabe analysieren?

  • echo $(ps cax | grep myapp | grep -o '^[ ]*[0-9]*')

und ich habe used it with exec.Command() aber ich möchte es vermeiden, wenn es eine bessere ist:

Ich habe einen Weg, um wieder die pid mit einem Befehl wie folgt gefunden Ansatz.

+0

Mögliche Duplikat [Liste der aktuell Prozess in Golang läuft] (http://stackoverflow.com/questions/9030680/list-of-currently-running-process-in-golang) – I159

+0

Es gibt keine andere Möglichkeit als einen externen Befehl auszuführen. – Nadh

Antwort

1

habe ich endlich etwas wie folgt aus:

// `echo "sudo_password" | sudo -S [command]` 
// is used in order to run the command with `sudo` 

_, err := exec.Command("sh", "-c", "echo '"+ sudopassword +"' | sudo -S pkill -SIGINT my_app_name").Output() 

if err != nil { 
    // ... 
} else { 
    // ... 
} 

Ich benutzte das SIGINT Signal anmutig die App zu stoppen.

Von wikipedia:

  • SIGINT

    Das SIGINT Signal an einen Prozess durch seinen Steueranschluss gesendet wird, wenn ein Benutzer den Prozess zu unterbrechen wünscht. Dies wird normalerweise durch Drücken von Strg + C ausgelöst, aber auf einigen Systemen kann das "Löschen" -Zeichen oder die "Abbrechen" -Taste verwendet werden.

  • SIGKILL

    SIGKILL Das Signal wird an einen Prozeß gesendet, um zu bewirken sofort (kill) zu beenden. Im Gegensatz zu SIGTERM und SIGINT kann dieses Signal nicht abgefangen oder ignoriert werden, und der Empfangsprozess kann beim Empfang dieses Signals keine Bereinigung durchführen. Es gelten folgende Ausnahmen:

+0

Aber, wie man Prozess tötet, wenn wir pid nicht kennen? – Priyanka

+0

Das obige Code-Snippet macht genau das, wonach Sie fragen. Sie kennen die 'pid' nicht, aber Sie müssen den' Namen' der ausführbaren Datei kennen, die Sie löschen möchten. Zum Beispiel, hier wird das Signal an 'my_app_name' gesendet – tgogos

+0

Ohh .. !! Ich habe Code nicht genau gesehen. Danke. – Priyanka

3

Das Ausführen externer Befehle ist wahrscheinlich der beste Weg, dies zu tun. Der folgende Code wird jedoch unter Ubuntu mindestens so lange ausgeführt, wie Sie der Besitzer des Prozesses zum Töten sind.

// killprocess project main.go 
package main 

import (
    "bytes" 
    "fmt" 
    "io" 
    "io/ioutil" 
    "log" 
    "os" 
    "path/filepath" 
    "strconv" 
    "strings" 
) 

// args holds the commandline args 
var args []string 

// findAndKillProcess walks iterative through the /process directory tree 
// looking up the process name found in each /proc/<pid>/status file. If 
// the name matches the name in the argument the process with the corresponding 
// <pid> will be killed. 
func findAndKillProcess(path string, info os.FileInfo, err error) error { 
    // We just return in case of errors, as they are likely due to insufficient 
    // privileges. We shouldn't get any errors for accessing the information we 
    // are interested in. Run as root (sudo) and log the error, in case you want 
    // this information. 
    if err != nil { 
     // log.Println(err) 
     return nil 
    } 

    // We are only interested in files with a path looking like /proc/<pid>/status. 
    if strings.Count(path, "/") == 3 { 
     if strings.Contains(path, "/status") { 

      // Let's extract the middle part of the path with the <pid> and 
      // convert the <pid> into an integer. Log an error if it fails. 
      pid, err := strconv.Atoi(path[6:strings.LastIndex(path, "/")]) 
      if err != nil { 
       log.Println(err) 
       return nil 
      } 

      // The status file contains the name of the process in its first line. 
      // The line looks like "Name: theProcess". 
      // Log an error in case we cant read the file. 
      f, err := ioutil.ReadFile(path) 
      if err != nil { 
       log.Println(err) 
       return nil 
      } 

      // Extract the process name from within the first line in the buffer 
      name := string(f[6:bytes.IndexByte(f, '\n')]) 

      if name == args[1] { 
       fmt.Printf("PID: %d, Name: %s will be killed.\n", pid, name) 
       proc, err := os.FindProcess(pid) 
       if err != nil { 
        log.Println(err) 
       } 
       // Kill the process 
       proc.Kill() 

       // Let's return a fake error to abort the walk through the 
       // rest of the /proc directory tree 
       return io.EOF 
      } 

     } 
    } 

    return nil 
} 

// main is the entry point of any go application 
func main() { 
    args = os.Args 
    if len(args) != 2 { 
     log.Fatalln("Usage: killprocess <processname>") 
    } 
    fmt.Printf("trying to kill process \"%s\"\n", args[1]) 

    err := filepath.Walk("/proc", findAndKillProcess) 
    if err != nil { 
     if err == io.EOF { 
      // Not an error, just a signal when we are done 
      err = nil 
     } else { 
      log.Fatal(err) 
     } 
    } 
} 

Es ist nur ein Beispiel, das sicherlich verbessert werden kann. Ich habe dies für Linux geschrieben und den Code auf Ubuntu 15.10 getestet. Es wird nicht unter Windows laufen.