web-dev-qa-db-ja.com

Golang-名前でプロセスを強制終了する

プロセス名しかわからない場合、Goコードでプロセスを強制終了する効果的な方法は何でしょうか? osパッケージによって提供される次のような関数がいくつかあります。

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

コマンドを実行してから出力を解析せずにpidを取得するための良い/一般的な方法はありますか?

次のようなコマンドを使用してpidを取り戻す方法を見つけました。

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

そして私は exec.Command() と一緒に使用しましたが、より良いアプローチがあれば避けたいと思います。

5
tgogos

私はついに次のようなものを使用しました:

// `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 {
    // ...
}

SIGINTシグナルを使用して、アプリを正常に停止しました。

から ウィキペディア

  • SIGINT

    SIGINTシグナルは、ユーザーがプロセスを中断したいときに、制御端末によってプロセスに送信されます。これは通常、Ctrl + Cを押すことで開始されますが、一部のシステムでは、「削除」文字または「ブレーク」キーを使用できます。

  • SIGKILL

    SIGKILLシグナルはプロセスに送信され、プロセスを即座に終了させます(kill)。 SIGTERMおよびSIGINTとは対照的に、このシグナルはキャッチまたは無視できず、受信プロセスはこのシグナルの受信時にクリーンアップを実行できません。次の例外が適用されます。

6
tgogos

これを行うには、おそらく外部コマンドを実行するのが最善の方法です。ただし、次のコードは、少なくともあなたがkillするプロセスの所有者である限り、Ubuntuで実行されます。

// 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)
        }
    }
}

これは確かに改善できる一例にすぎません。私はこれをLinux用に作成し、Ubuntu15.10でコードをテストしました。 Windowsでは動作しません。

8
Peter Gloor