Skip to content

Commit

Permalink
Ability to run in background
Browse files Browse the repository at this point in the history
  • Loading branch information
willnode committed Oct 26, 2024
1 parent 0c5bc6a commit 6626536
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 13 deletions.
68 changes: 55 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,36 +1,78 @@
package main

import (
"bytes"
"fmt"
"net"
"os"
"os/exec"
"strconv"
)

var outPort int

func init() {
var err error
outPort, err = getFreePort()

outPort, err = checkExistingProcess()
if err == nil && isPortListening(outPort) {
fmt.Printf("Process is already running on port %d\n", outPort)
return
}

// No existing process found or not listening, start a new one
outPort, err := getFreePort()
if err != nil {
panic("Can't get free port")
}

args := os.Args
bg := os.Getenv("NOHUP") == "1"

// Check if there are additional arguments
if len(os.Args) > 1 {
cmd := exec.Command(os.Args[1], os.Args[2:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, fmt.Sprintf("PORT=%d", outPort))
if len(args) > 1 {
if bg {
var out bytes.Buffer
var stderr bytes.Buffer
cmdd := generateBgCmd(args[1], args[2:]...)
cmd := exec.Command("bash", "-c", cmdd)
cmd.Stdout = &out
cmd.Stderr = &stderr
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, fmt.Sprintf("PORT=%d", outPort))
err = cmd.Run()
if err != nil {
fmt.Printf("Error starting command: %v\n", err)
os.Exit(1)
}
pid, err := strconv.Atoi(out.String())
if nil != err {
fmt.Printf("Error starting command: %v\n", err)
os.Exit(1)
}
if pid == 0 {
fmt.Printf("invalid PID of 0")
os.Exit(1)
}
writePidPortFile(pid, outPort)
fmt.Printf("Started process %s with PID %d in background\n", args[1], pid)
} else {
cmd := exec.Command(args[1], args[2:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, fmt.Sprintf("PORT=%d", outPort))

// Start the specified command
err := cmd.Start()
if err != nil {
fmt.Printf("Error starting command: %v\n", err)
os.Exit(1)
// Start the specified command
err := cmd.Start()
if err != nil {
fmt.Printf("Error starting command: %v\n", err)
os.Exit(1)
}
pid := cmd.Process.Pid
fmt.Printf("Started process %s with PID %d\n", args[1], pid)
}

fmt.Printf("Started process %s with PID %d\n", os.Args[1], cmd.Process.Pid)
}
}

Expand Down
70 changes: 70 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package main

import (
"fmt"
"net"
"net/http"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"syscall"
"time"
)

Expand Down Expand Up @@ -31,3 +37,67 @@ func filterInvalidHeaders(headers http.Header) {
}
}
}

func getPidFile() string {
return filepath.Join(os.Getenv("HOME"), "tmp", "app.pid")
}

func checkExistingProcess() (int, error) {
data, err := os.ReadFile(getPidFile())
if err != nil {
return 0, err
}

fields := strings.Split(string(data), ":")
if len(fields) != 2 {
return 0, fmt.Errorf("invalid pid/port file format")
}

pid, err := strconv.Atoi(fields[0])
if err != nil {
return 0, fmt.Errorf("invalid PID format: %v", err)
}

port, err := strconv.Atoi(fields[1])
if err != nil {
return 0, fmt.Errorf("invalid port format: %v", err)
}

if processExists(pid) {
return port, nil
}
return 0, fmt.Errorf("no running process found")
}

func processExists(pid int) bool {
process, err := os.FindProcess(pid)
if err != nil {
return false
}
err = process.Signal(syscall.Signal(0))
return err == nil
}

func isPortListening(port int) bool {
conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port))
if err != nil {
return false
}
conn.Close()
return true
}

func writePidPortFile(pid, port int) {
err := os.WriteFile(getPidFile(), []byte(fmt.Sprintf("%d:%d", pid, port)), 0644)
if err != nil {
fmt.Printf("Failed to write PID/port file: %v\n", err)
}
}

func generateBgCmd(name string, arg ...string) string {
return fmt.Sprintf(
"nohup %s %s < /dev/null &>$HOME/tmp/app.log & echo -n $! | awk '/[0-9]+$/{ printf $0 }'",
name,
strings.Join(arg, " "),
)
}

0 comments on commit 6626536

Please sign in to comment.