add start, fgstart, stop, status subcommands
Modelled after 9p/main.go. Pid file in 9P namespace dir; running check via TCP dial to -listen address. No-subcommand path preserved for backwards compatibility. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
14bcbf0646
commit
4338acd2df
97
main.go
97
main.go
|
|
@ -17,9 +17,14 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"9fans.net/go/plan9"
|
||||
"9fans.net/go/plan9/client"
|
||||
|
|
@ -35,8 +40,100 @@ var (
|
|||
addr = flag.String("addr", "", "9P server address; empty = use namespace service")
|
||||
)
|
||||
|
||||
const pidFile = "ollie-httpgw.pid"
|
||||
|
||||
func main() {
|
||||
if len(os.Args) >= 2 {
|
||||
subcmd := os.Args[1]
|
||||
switch subcmd {
|
||||
case "start", "fgstart", "stop", "status":
|
||||
flag.CommandLine.Parse(os.Args[2:]) //nolint:errcheck
|
||||
ns := client.Namespace()
|
||||
if ns == "" {
|
||||
fmt.Fprintln(os.Stderr, "no namespace")
|
||||
os.Exit(1)
|
||||
}
|
||||
pidPath := filepath.Join(ns, pidFile)
|
||||
switch subcmd {
|
||||
case "start":
|
||||
if gwRunning() {
|
||||
fmt.Println("ollie-httpgw already running")
|
||||
os.Exit(0)
|
||||
}
|
||||
daemonize()
|
||||
case "fgstart":
|
||||
if gwRunning() {
|
||||
fmt.Println("ollie-httpgw already running")
|
||||
os.Exit(0)
|
||||
}
|
||||
runGateway(pidPath)
|
||||
case "stop":
|
||||
stopGateway(pidPath)
|
||||
case "status":
|
||||
if gwRunning() {
|
||||
fmt.Println("ollie-httpgw running")
|
||||
} else {
|
||||
fmt.Println("ollie-httpgw not running")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
// Legacy: no subcommand — run in foreground directly (no pid file).
|
||||
flag.Parse()
|
||||
serve()
|
||||
}
|
||||
|
||||
func gwRunning() bool {
|
||||
conn, err := net.Dial("tcp", *listen)
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func daemonize() {
|
||||
exe, _ := os.Executable()
|
||||
args := []string{"fgstart", "-listen", *listen, "-service", *service}
|
||||
if *network != "" {
|
||||
args = append(args, "-net", *network)
|
||||
}
|
||||
if *addr != "" {
|
||||
args = append(args, "-addr", *addr)
|
||||
}
|
||||
cmd := exec.Command(exe, args...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||
if err := cmd.Start(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to start: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("ollie-httpgw started (pid %d)\n", cmd.Process.Pid)
|
||||
}
|
||||
|
||||
func stopGateway(pidPath string) {
|
||||
data, err := os.ReadFile(pidPath)
|
||||
if err != nil {
|
||||
fmt.Println("ollie-httpgw not running")
|
||||
return
|
||||
}
|
||||
var pid int
|
||||
fmt.Sscanf(string(data), "%d", &pid)
|
||||
if pid > 0 {
|
||||
syscall.Kill(pid, syscall.SIGTERM) //nolint:errcheck
|
||||
}
|
||||
os.Remove(pidPath) //nolint:errcheck
|
||||
fmt.Println("ollie-httpgw stopped")
|
||||
}
|
||||
|
||||
func runGateway(pidPath string) {
|
||||
os.WriteFile(pidPath, fmt.Appendf(nil, "%d", os.Getpid()), 0644) //nolint:errcheck
|
||||
serve()
|
||||
os.Remove(pidPath) //nolint:errcheck
|
||||
}
|
||||
|
||||
func serve() {
|
||||
http.HandleFunc("/openapi.json", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(openapiSpec)
|
||||
|
|
|
|||
Loading…
Reference in New Issue