In this tutorial we will cover different scenarios to kill a process using golang code. We will use different in-built functions to achieve this requirement.
Method-1: Kill a process using Process.Signal()
In this code we start a process using exec.Command()
and then will kill the same process using Process.Signal()
function. For example, we can use syscall.SIGTERM
to send the SIGTERM signal, which is the default signal sent by the kill
command. This signal can be caught by the process and it can perform cleanup before exiting.
package main
import (
"fmt"
"os/exec"
"time"
)
func main() {
cmd := exec.Command("sleep", "100")
err := cmd.Start()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Process started with PID:", cmd.Process.Pid)
// Kill the process after 5 seconds
<-time.After(5 * time.Second)
err = cmd.Process.Kill()
if err != nil {
fmt.Println(err)
}
fmt.Println("Process killed with PID:", cmd.Process.Pid)
}
We can use the Process.Signal
method, the process can catch this signal and perform any cleanup before exiting.
Output:
# go run main.go
Process started with PID: 4538
Process killed with PID: 4538
Method-2: Kill parent and all child processes using syscall.Kill()
If we have a requirement to kill the parent and all it's child process then this can also be achieved by using the os.FindProcess
function to find the parent process, and then use the syscall.Kill
function to send a signal to the parent process and all its child processes.
package main
import (
"fmt"
"os/exec"
"strings"
)
func main() {
// Generate a parent process
cmd := exec.Command("sh", "-c", "ping google.com -c 5 & ping yahoo.com -c 5 &")
cmd.Start()
fmt.Printf("Parent PID: %d\n", cmd.Process.Pid)
//listing the child process
output, _ := exec.Command("ps", "-o", "pid", "-C", "ping").Output()
fields := strings.Fields(string(output))
for i := 1; i < len(fields); i++ {
fmt.Printf("PID of ping: %s\n", fields[i])
}
// Kill the parent and child process
cmd.Process.Kill()
}
This program creates a parent process using the exec.Command
function, it runs sh -c "ping google.com -c 5 & ping yahoo.com -c 5 &"
command which will ping google.com and yahoo.com five times each in background. Then it uses the ps -o pid -C ping
command to list the child process. It filters the output based on command name "ping
" using -C
option, and using strings.Fields(string(output))
function to split the output into individual fields. Finally, it kills the parent and child process using the cmd.Process.Kill()
function.
Output:
# go run main.go
Parent PID: 12307
PID of ping: 12309
PID of ping: 12310
Also in other terminal we can see the ping process running with same PIDs
~]# ps -ef | grep ping root 12309 1 0 22:39 pts/0 00:00:00 ping google.com -c 5 root 12310 1 0 22:39 pts/0 00:00:00 ping yahoo.com -c 5 root 12328 5835 0 22:39 pts/1 00:00:00 grep --color=auto ping
Method-3: Killing a process by name instead of PID
In this example code we will kill process by name instead of their pid by using pkill()
package main
import (
"fmt"
"os/exec"
"strings"
)
func KillProcessByName(name string) error {
// Get the process information by name
output, _ := exec.Command("ps", "-o", "pid,comm", "-C", name).Output()
lines := strings.Split(string(output), "\n")
for i, line := range lines {
if i == 0 {
continue
}
fields := strings.Fields(line)
if len(fields) < 2 {
continue
}
fmt.Printf("Killing process: %s (PID: %s)\n", fields[1], fields[0])
// Kill the process
exec.Command("pkill", "-f", fields[0]).Run()
}
return nil
}
func main() {
// Generate a child process
cmd := exec.Command("sh", "-c", "ping google.com -c 5 & ping yahoo.com -c 5 &")
cmd.Start()
fmt.Printf("Child PID: %d\n", cmd.Process.Pid)
// Kill the child process by name
err := KillProcessByName("ping")
if err != nil {
fmt.Printf("Error: %v\n", err)
}
}
Explanation:
- The
KillProcessByName(name string)
function is defined, which takes the name of the process as an input. - Inside the function, it runs the command
ps -o pid,comm -C name
which lists the process information based on the command name. The -o option is used to specify the output format, and thepid,comm
specifies that the output should show the process ID and command name. The-C
option is used to filter the process based on command name, in this case name. - The output of the command is stored in the output variable, which is then split into multiple lines using
strings.Split(string(output), "\n")
function. - The code then iterates over the lines, for each line it uses
strings.Fields(line)
function to split the line into individual fields. The first field is the process ID, the second field is the process name. - It then prints the process name and PID before killing it using the
pkill
 command for each of them. Thepkill
 command sends the SIGKILL signal to the process, which will forcefully terminate it. - If there is any error it will be returned otherwise it returns nil.
Output:
# go run main.go Child PID: 15582 Killing process: ping (PID: 15584) Killing process: ping (PID: 15585)
Summary
In Golang, we have several options to kill a process, such as:
- The Kill method on the Cmd struct returned by the
exec.Command
function sends the SIGKILL signal to the process, which cannot be caught or ignored and will force the process to exit immediately. - The
Process.Signal
method can be used to send a specific signal to the process. For example, you can usesyscall.SIGTERM
to send theSIGTERM
signal, which is the default signal sent by thekill
command. This signal can be caught by the process and it can perform cleanup before exiting. - The
Process.Kill
method is similar toKill
method of Cmd struct but it uses the underlyingsyscall.Kill
function.
Further Reading
os/signal - Go Packages
syscall - Go Packages