Process.go

package core

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"
)

// Execute ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
func Execute(command string) error {
	if runtime.GOOS == "windows" {
		cmd := exec.Command("cmd", "/C", command)
		return cmd.Start()
	} else {
		cmd := exec.Command("sh", "-c", command+" > /dev/null 2>&1 &")
		return cmd.Start()
	}
}

// Spawn ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ ๋ฐ”์ด๋„ˆ๋ฆฌ์™€ ์„œ๋น„์Šค๋ฅผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
func Spawn(bin string, service string, inputs []string) error {
	log("Spawn process.. " + service)

	if runtime.GOOS == "windows" {
		args := append([]string{"php", bin, service}, inputs...)
		cmd := exec.Command("cmd", "/C", strings.Join(args, " "))
		return cmd.Start()
	} else {
		php, err := exec.LookPath("php")
		if err != nil {
			return err
		}
		args := append([]string{php, bin, "run", service}, inputs...)
		cmd := exec.Command("sh", "-c", strings.Join(args, " ")+" > /dev/null 2>&1 &")
		return cmd.Start()
	}
}

// Fork ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ ๋ฐ”์ด๋„ˆ๋ฆฌ์™€ ์„œ๋น„์Šค๋ฅผ ์ƒˆ๋กœ์šด ์„ธ์…˜์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
func Fork(bin string, service string, inputs []string) error {
	log("Fork process.. " + service)

	if runtime.GOOS == "windows" {
		return fmt.Errorf("Fork is not supported on Windows")
	}

	php, err := exec.LookPath("php")
	if err != nil {
		return err
	}

	args := append([]string{php, bin, service}, inputs...)
	cmd := exec.Command(php, args...)
	cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
	return cmd.Start()
}

// IsRunning ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ PID์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
func IsRunning(pid int) bool {
	if runtime.GOOS == "windows" {
		cmd := exec.Command("tasklist", "/NH", "/FO", "CSV", "/FI", fmt.Sprintf("PID eq %d", pid))
		output, err := cmd.Output()
		if err != nil {
			fmt.Println("Error checking process:", err)
			return false
		}
		return strings.Contains(string(output), fmt.Sprintf("%d", pid))
	} else {
		process, err := os.FindProcess(pid)
		if err != nil {
			return false
		}
		err = process.Signal(syscall.Signal(0))
		return err == nil
	}
}

// Destroy ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ PID์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ•์ œ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
func Destroy(pid int) error {
	log(fmt.Sprintf("Kill process.. %d ", pid))

	if runtime.GOOS == "windows" {
		cmd := exec.Command("taskkill", "/PID", fmt.Sprintf("%d", pid), "/F")
		return cmd.Run()
	} else {
		process, err := os.FindProcess(pid)
		if err != nil {
			return err
		}
		return process.Kill()
	}
}

// log ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. (์ž„์‹œ๋กœ fmt.Println์œผ๋กœ ๋Œ€์ฒด)
func log(message string) {
	fmt.Println(message)
	// ์—ฌ๊ธฐ์— ํ•„์š”ํ•œ ๋กœ๊ทธ ๊ธฐ๋ก ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”
}

์ฃผ์š” ํ•จ์ˆ˜

  1. Execute ํ•จ์ˆ˜

    • ์—ญํ• : ์ฃผ์–ด์ง„ ๋ช…๋ น์–ด๋ฅผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    • ๋™์ž‘ ๋ฐฉ์‹:

      • ์šด์˜์ฒด์ œ๊ฐ€ ์œˆ๋„์šฐ์ธ ๊ฒฝ์šฐ cmd /C๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

      • ์œ ๋‹‰์Šค ๊ณ„์—ด์ธ ๊ฒฝ์šฐ sh -c๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ น์–ด๋ฅผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•˜๊ณ  ์ถœ๋ ฅ์€ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

      • cmd.Start()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  2. Spawn ํ•จ์ˆ˜

    • ์—ญํ• : ์ฃผ์–ด์ง„ ์„œ๋น„์Šค์™€ ์ž…๋ ฅ์œผ๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    • ๋™์ž‘ ๋ฐฉ์‹:

      • ์œˆ๋„์šฐ์ธ ๊ฒฝ์šฐ cmd /C๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ php ์‹คํ–‰ ํŒŒ์ผ๊ณผ ํ•จ๊ป˜ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

      • ์œ ๋‹‰์Šค ๊ณ„์—ด์ธ ๊ฒฝ์šฐ exec.LookPath๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ php ์‹คํ–‰ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๊ณ , sh -c๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

      • ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ๋ช…๋ น์–ด๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

  3. Fork ํ•จ์ˆ˜

    • ์—ญํ• : ์ƒˆ๋กœ์šด ์„ธ์…˜์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    • ๋™์ž‘ ๋ฐฉ์‹:

      • ์œˆ๋„์šฐ์—์„œ๋Š” Fork๊ฐ€ ์ง€์›๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

      • ์œ ๋‹‰์Šค ๊ณ„์—ด์—์„œ๋Š” php ์‹คํ–‰ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„ ์ƒˆ๋กœ์šด ์„ธ์…˜์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

      • syscall.SysProcAttr{Setsid: true}๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ์„ธ์…˜์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  4. IsRunning ํ•จ์ˆ˜

    • ์—ญํ• : ์ฃผ์–ด์ง„ PID์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    • ๋™์ž‘ ๋ฐฉ์‹:

      • ์œˆ๋„์šฐ์—์„œ๋Š” tasklist ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

      • ์œ ๋‹‰์Šค ๊ณ„์—ด์—์„œ๋Š” os.FindProcess๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฐพ๊ณ , Signal(0)์„ ๋ณด๋‚ด์„œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

  5. Destroy ํ•จ์ˆ˜

    • ์—ญํ• : ์ฃผ์–ด์ง„ PID์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

    • ๋™์ž‘ ๋ฐฉ์‹:

      • ์œˆ๋„์šฐ์—์„œ๋Š” taskkill ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

      • ์œ ๋‹‰์Šค ๊ณ„์—ด์—์„œ๋Š” os.FindProcess๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฐพ๊ณ  Kill ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

  6. log ํ•จ์ˆ˜

    • ์—ญํ• : ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

    • ๋™์ž‘ ๋ฐฉ์‹:

      • ์ฃผ์–ด์ง„ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

      • ์‹ค์ œ ๋กœ๊ทธ ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๋ ค๋ฉด ์ถ”๊ฐ€ ๋กœ์ง์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์š”์•ฝ

์ด ๋ชจ๋“ˆ์€ ์šด์˜์ฒด์ œ์— ๋”ฐ๋ผ ์™ธ๋ถ€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Execute ํ•จ์ˆ˜๋Š” ๋‹จ์ˆœํžˆ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ณ , Spawn ํ•จ์ˆ˜๋Š” ์ฃผ์–ด์ง„ ์ž…๋ ฅ์œผ๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. Fork ํ•จ์ˆ˜๋Š” ์ƒˆ๋กœ์šด ์„ธ์…˜์—์„œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ์œˆ๋„์šฐ์—์„œ๋Š” ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. IsRunning ํ•จ์ˆ˜๋Š” ํŠน์ • PID์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•˜๊ณ , Destroy ํ•จ์ˆ˜๋Š” ํŠน์ • PID์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. log ํ•จ์ˆ˜๋Š” ๊ฐ„๋‹จํžˆ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

Last updated