-3

I know we can start another app from the Go code using https://golang.org/pkg/os/exec/#example_Cmd_Run

Is there a way to close/shut another app/process from my code, for example I want want to close MS excel if it is running.

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203

1 Answers1

0

If you are running the application.service from you go code using the Command, like:

// Start a process:
import "os/exec"
cmd := exec.Command("code", ".")
if err := cmd.Start(); err != nil {
    log.Fatal(err)
}

Then you can kill it from the same code using exec.Process as:

// Kill it:
if err := cmd.Process.Kill(); err != nil {
    log.Fatal("failed to kill process: ", err)
}

Other wise you need to read the process id, then kill it, go-ps will help in this task, this should be helpfullfor you.

If the application to be terminatd a web server, you need to get the PID and terminate it, in some caes the application is closed while the port is not freed, beow are the typical command to get the PID and free the port (checked at Mac)

    $ lsof -i tcp:8090   OR lsof -i :<port>
    $ lsof -P | grep ':8090' | awk '{print $2}'  // return PID number only
    $ ps ax | grep <PID> return status of the PID
    $ kill -QUIT <PID>
// Or
$ lsof -P | grep ':<port>' | awk '{print $2}' | xargs kill -9

If the plan is to kill a webserver from another webserver, you can make a route to return the server to be shut down PID, as:

func pid(w http.ResponseWriter, req *http.Request) {

    pid := fmt.Sprint(os.Getpid())
    fmt.Fprintf(w, pid)
}

Then in your main app, you can call the PID and kill the server as:

    resp, err := http.Get("http://localhost:port/pid")
    if err != nil {
        // handle error
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    byteToInt, _ := strconv.Atoi(string(body))
    proc, err := os.FindProcess(byteToInt)
    if err != nil {
        log.Fatalf("Error reading the process = %v", err)
    }
    // Kill it:
    if err := proc.Kill(); err != nil {
        log.Fatal("failed to kill process: ", err)
    }

    /* Enfore port cleaning
        proc, err = os.FindProcess(8090)
        if err != nil {
            fmt.Printf("Error reading the process = %v", err)
        }
        // Kill it:
        if err := proc.Kill(); err != nil {
            fmt.Printf("failed to kill process: ", err)
        }
    */

If you are going to use this ractice, it could be a good idea to make sure the port is free before creating the server, as below:

    port := "8090"
    byteToInt, _ := strconv.Atoi(port)
    proc, err := os.FindProcess(byteToInt)
    if err != nil {
        log.Fatalf("Error reading the process = %v", err)
    }
    // Kill it:
    if err := proc.Kill(); err != nil {
        fmt.Println("port ready for use")
    } else {
        fmt.Println("port had been cleaned")
    }

    http.ListenAndServe(":"+port, nil)
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203