Golang : Get executable name behind process ID example




Problem:

You want to check if a process is actually running and at the same time you want to find out the application/executable/binary name associated with the process ID. How to do that?

Solution:

We will use the standard os and syscall functions to determine if a process is running and alive. To get the application/executable or binaray name associated with the process ID, we will use Mitchell Hashimoto's https://github.com/mitchellh/go-ps package.

To test out the program below, pluck some process ids from ps command on Linux/Unix or on Windows use the task manager

NOTE : You will not be able to query some processes because you're not the owner.

Here you go!


 package main

 import (
  "errors"
  "fmt"
  ps "github.com/mitchellh/go-ps"
  "os"
  "runtime"
  "strconv"
  "syscall"
 )

 // check if the process is actually running
 // However, on Unix systems, os.FindProcess always succeeds and returns
 // a Process for the given pid...regardless of whether the process exists
 // or not.
 func getProcessRunningStatus(pid int) (*os.Process, error) {
  proc, err := os.FindProcess(pid)
  if err != nil {
 return nil, err
  }

  //double check if process is running and alive
  //by sending a signal 0
  //NOTE : syscall.Signal is not available in Windows

  err = proc.Signal(syscall.Signal(0))
  if err == nil {
 return proc, nil
  }

  if err == syscall.ESRCH {
 return nil, errors.New("process not running")
  }

  // default
  return nil, errors.New("process running but query operation not permitted")
 }

 func main() {

  if len(os.Args) != 2 {
 fmt.Printf("Usage : %s processID \n ", os.Args[0]) // return the program name back to %s
 os.Exit(1) // graceful exit
  }

  pid, err := strconv.Atoi(os.Args[1])

  if err != nil {
 fmt.Println("Bad process ID supplied")
 os.Exit(-1)
  }

  //NOTE : syscall.Signal is not available in Windows
  if runtime.GOOS != "windows" {
 _, err := getProcessRunningStatus(int(pid))

 if err != nil {
 fmt.Println("Error : ", err)
 os.Exit(-1)
 }

  }

  // at this stage the Processes related functions found in Golang's OS package
  // is no longer sufficient, we will use Mitchell Hashimoto's https://github.com/mitchellh/go-ps
  // package to find the application/executable/binary name behind the process ID.

  p, err := ps.FindProcess(pid)

  if err != nil {
 fmt.Println("Error : ", err)
 os.Exit(-1)
  }

  fmt.Println("Process ID : ", p.Pid())
  fmt.Println("Parent Process ID : ", p.PPid())
  fmt.Println("Process ID binary name : ", p.Executable())

 }

Sample output on Mac:

./checkprocess 387

Process ID : 387

Parent Process ID : 1

Process ID binary name : Google Drive

./checkprocess 392

Process ID : 392

Parent Process ID : 1

Process ID binary name : Dropbox

./checkprocess 398

Error : process running but query operation not permitted

Sample output on Windows:

C:\work>checkprocess 8112

Process ID : 8112

Parent Process ID : 2944

Process ID binary name : cmd.exe

C:\work>checkprocess 3972

Process ID : 3972

Parent Process ID : 824

Process ID binary name : chrome.exe

C:\work>checkprocess 8132

Process ID : 8132

Parent Process ID : 236

Process ID binary name : CCC.exe

References:

https://golang.org/pkg/os/#FindProcess

https://www.socketloop.com/tutorials/golang-get-command-line-arguments

https://github.com/mitchellh/go-ps/blob/master/process.go

  See also : Golang : Multi threading or run two processes or more example





By Adam Ng

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement