Skip to content

Commit

Permalink
fix: no output when RunAsDaemon is false in windows
Browse files Browse the repository at this point in the history
  • Loading branch information
yuweizzz committed May 22, 2023
1 parent b137a33 commit 8ffb937
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 123 deletions.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
MAIN := main.go
SIDECAR := sidecar
LD_FLAGS := "-s -w"

CURDIR := $(shell pwd)
OUTPUTDIR := build
Expand All @@ -18,11 +19,11 @@ mac: clean build_mac copy_tpl

.PHONY: build_linux build_windows build_mac copy_tpl
build_linux:
GOARCH="amd64" GOOS="linux" go build -o $(OUTPUTDIR)/$(SIDECAR) $(SIDECAR_DIR)/$(MAIN)
GOARCH="amd64" GOOS="linux" go build -ldflags=$(LD_FLAGS) -o $(OUTPUTDIR)/$(SIDECAR) $(SIDECAR_DIR)/$(MAIN)
build_windows:
GOARCH="amd64" GOOS="windows" go build -ldflags="-H windowsgui" -o $(OUTPUTDIR)/sidecar.exe $(SIDECAR_DIR)/$(MAIN)
GOARCH="amd64" GOOS="windows" go build -ldflags=$(LD_FLAGS) -o $(OUTPUTDIR)/sidecar.exe $(SIDECAR_DIR)/$(MAIN)
build_mac:
GOARCH="amd64" GOOS="darwin" go build -o $(OUTPUTDIR)/$(SIDECAR) $(SIDECAR_DIR)/$(MAIN)
GOARCH="amd64" GOOS="darwin" go build -ldflags=$(LD_FLAGS) -o $(OUTPUTDIR)/$(SIDECAR) $(SIDECAR_DIR)/$(MAIN)
copy_tpl:
cp nginx_conf.tpl $(OUTPUTDIR)/nginx_conf.tpl
cp config_toml.tpl $(OUTPUTDIR)/config.toml
Expand Down
74 changes: 10 additions & 64 deletions cmd/sidecar/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ import (
"flag"
"fmt"
"os"
"os/exec"
"path"
"runtime"
"strconv"
"syscall"

"github.com/yuweizzz/sidecar"
)
Expand All @@ -35,7 +31,7 @@ func main() {
configServerPath := serverCmd.String("conf", pwd+"/config.toml", "the path of sidecar conf")
serverAction := serverCmd.String("action", "", "action must in ['start', 'stop', 'create-nginx-conf']")

// for run as daemon
// run as daemon, use function sidecar.StartDaemonProcess() to start
if len(os.Args) < 2 {
if os.Getenv("SPECIAL_MARK") == "ENABLED" {
path := os.Getenv("CONF_PATH")
Expand All @@ -60,36 +56,12 @@ func main() {
switch *clientAction {
case "start":
if cfg.Client.RunAsDaemon {
cmd := &exec.Cmd{
Path: os.Args[0],
Env: []string{"SPECIAL_MARK=ENABLED", "CONF_PATH=" + *configClientPath, "TYPE=client"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err := cmd.Start()
if err != nil {
panic(err)
}
os.Exit(0)
sidecar.StartDaemonProcess(*configClientPath, "client")
} else {
runClient(cfg)
}
case "stop":
lockPath := cfg.Client.WorkDir + "/sidecar.lock"
pid := sidecar.ReadLock(lockPath)
// if lock exist
if pid != 0 {
proc, _ := os.FindProcess(pid)
if runtime.GOOS == "windows" {
sidecar.RemoveLock(lockPath)
proc.Kill()
} else {
proc.Signal(syscall.SIGINT)
}
fmt.Println("Now Server is stopped.")
} else {
fmt.Println("Now sidecar.lock is not exist, server is stopped")
}
sidecar.StopDaemonProcess(cfg.Client.WorkDir)
default:
help(filename)
}
Expand All @@ -99,35 +71,12 @@ func main() {
switch *serverAction {
case "start":
if cfg.Server.RunAsDaemon {
cmd := &exec.Cmd{
Path: os.Args[0],
Env: []string{"SPECIAL_MARK=ENABLED", "CONF_PATH=" + *configServerPath, "TYPE=server"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err := cmd.Start()
if err != nil {
panic(err)
}
os.Exit(0)
sidecar.StartDaemonProcess(*configServerPath, "server")
} else {
runServer(cfg)
}
case "stop":
lockPath := cfg.Server.WorkDir + "/sidecar.lock"
pid := sidecar.ReadLock(lockPath)
if pid != 0 {
proc, _ := os.FindProcess(pid)
if runtime.GOOS == "windows" {
sidecar.RemoveLock(lockPath)
proc.Kill()
} else {
proc.Signal(syscall.SIGINT)
}
fmt.Println("Now Server is stopped.")
} else {
fmt.Println("Now sidecar.lock is not exist, server is stopped")
}
sidecar.StopDaemonProcess(cfg.Server.WorkDir)
case "create-nginx-conf":
sidecar.RenderTemplateByConfig(cfg.Server.WorkDir, cfg)
default:
Expand All @@ -147,24 +96,24 @@ func runClient(cfg *sidecar.Config) {
LogLevel: cfg.Client.LogLevel,
}
daemon.Perpare(cfg.Client.RunAsDaemon)
remoteServer := cfg.Client.RemoteServers[0]
switch cfg.Client.Mode {
case "WSS":
pac := sidecar.NewPac(cfg.Client.RemoteServers[0], cfg.Client.GfwListUrl, cfg.Client.CustomProxyHosts)
pac := sidecar.NewPac(remoteServer, cfg.Client.GfwListUrl, cfg.Client.CustomProxyHosts)
proxy := sidecar.NewProxyViaWss(daemon.Logger, pac, cfg.Client.OnlyListenIPv4, cfg.Client.ProxyPort,
cfg.Client.RemoteServers[0].Host, cfg.Client.RemoteServers[0].ComplexPath, cfg.Client.RemoteServers[0].CustomHeaders)
remoteServer.Host, remoteServer.ComplexPath, remoteServer.CustomHeaders)
go proxy.Run()
default: // HTTPS
daemon.LoadCertAndPriKey()
pac := sidecar.NewPac(cfg.Client.RemoteServers[0], cfg.Client.GfwListUrl, cfg.Client.CustomProxyHosts)
pac := sidecar.NewPac(remoteServer, cfg.Client.GfwListUrl, cfg.Client.CustomProxyHosts)
proxy := sidecar.NewProxyViaHttps(daemon.Logger, pac, cfg.Client.OnlyListenIPv4, cfg.Client.ProxyPort)
cache := sidecar.NewCertLRU(daemon.Cert, daemon.PriKey)
mitm := sidecar.NewMitMServer(proxy.Listener, cache, daemon.Logger,
cfg.Client.RemoteServers[0].Host, cfg.Client.RemoteServers[0].ComplexPath, cfg.Client.RemoteServers[0].CustomHeaders)
remoteServer.Host, remoteServer.ComplexPath, remoteServer.CustomHeaders)
go proxy.Run()
go mitm.Run()
}
sidecar.Info("Now Server is run as a Client.")
sidecar.Info("Now Server is running and pid is " + strconv.Itoa(daemon.Pid))
daemon.WatchSignal()
}

Expand All @@ -177,8 +126,6 @@ func runServer(cfg *sidecar.Config) {
LogLevel: cfg.Server.LogLevel,
}
daemon.Perpare(cfg.Server.RunAsDaemon)
sidecar.Info("Server privatekey file: ", daemon.CertPath)
sidecar.Info("Server certificate file: ", daemon.PriKeyPath)
switch cfg.Server.Mode {
case "WSS":
server := sidecar.NewRemoteServerWss(daemon.Logger, cfg.Server.ServerPort, cfg.Server.OnlyListenIPv4,
Expand All @@ -190,6 +137,5 @@ func runServer(cfg *sidecar.Config) {
go server.Run()
}
sidecar.Info("Now Server is run as a Server.")
sidecar.Info("Now Server is running and pid is " + strconv.Itoa(daemon.Pid))
daemon.WatchSignal()
}
138 changes: 82 additions & 56 deletions daemon.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build linux || darwin
// +build linux darwin

package sidecar

import (
Expand All @@ -6,8 +9,8 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"os/signal"
"runtime"
"strconv"
"syscall"
)
Expand All @@ -24,9 +27,47 @@ type Daemon struct {
Cert *x509.Certificate
}

func readLock(path string) (pid int) {
lock := DetectFile(path)
if lock == "" {
return 0
} else {
bytes, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
pid, err = strconv.Atoi(string(bytes))
if err != nil {
panic(err)
}
return
}
}

func writeLock(pid int, path string) {
pid_str := strconv.Itoa(pid)
err := ioutil.WriteFile(path, []byte(pid_str), 0444)
if err != nil {
panic(err)
}
}

func removeLock(path string) {
err := os.Remove(path)
if err != nil {
panic(err)
}
Info("Remove sidecar.lock done.")
}

func exitWhenLocked(pid int) {
fmt.Println("Start Server failed because sidecar.lock exist, maybe Server is already running and pid is", pid)
fmt.Println("If you confirm Server is not running, remove sidecar.lock and retry.")
os.Exit(2)
}

func (d *Daemon) Perpare(backgroud bool) {
if backgroud {
fmt.Println(d.WorkDir)
log_fd := CreateFileIfNotExist(d.WorkDir + "/sidecar.log")
if log_fd == nil {
log_fd = OpenExistFile(d.WorkDir + "/sidecar.log")
Expand All @@ -36,22 +77,18 @@ func (d *Daemon) Perpare(backgroud bool) {
d.Logger = os.Stdout
}
Initial(d.LogLevel, d.Logger)
pid := ReadLock(d.LockFilePath)
pid := readLock(d.LockFilePath)
Info("Detect if Server is running .....")
// if lock exist
if pid != 0 {
if runtime.GOOS == "linux" {
alive := DetectProcess(pid)
// if process alive
if alive {
exitWhenLocked(pid)
} else {
// if process not alive
Info("File sidecar.lock exist, file path is ", d.LockFilePath, ", but process is not running.....")
RemoveLock(d.LockFilePath)
}
} else {
alive := DetectProcess(pid)
// if process alive
if alive {
exitWhenLocked(pid)
} else {
// if process not alive
Info("File sidecar.lock exist, file path is ", d.LockFilePath, ", but process is not running.....")
removeLock(d.LockFilePath)
}
}
d.Pid = os.Getpid()
Expand All @@ -77,44 +114,6 @@ func (d *Daemon) LoadCertAndPriKey() {
}
}

func ReadLock(path string) (pid int) {
lock := DetectFile(path)
if lock == "" {
return 0
} else {
bytes, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
pid, err = strconv.Atoi(string(bytes))
if err != nil {
panic(err)
}
return
}
}

func writeLock(pid int, path string) {
pid_str := strconv.Itoa(pid)
err := ioutil.WriteFile(path, []byte(pid_str), 0444)
if err != nil {
panic(err)
}
}

func RemoveLock(path string) {
err := os.Remove(path)
if err != nil {
panic(err)
}
}

func exitWhenLocked(pid int) {
fmt.Println("Start Server failed because sidecar.lock exist, maybe Server is already running and pid is ", pid)
fmt.Println("If you confirm Server is not running, remove sidecar.lock and retry.")
os.Exit(2)
}

func (d *Daemon) WatchSignal() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
Expand All @@ -123,9 +122,36 @@ func (d *Daemon) WatchSignal() {
<-sigs
done <- true
}()
Info("Awaiting signal......")
Info("Now Server is running and pid is " + strconv.Itoa(d.Pid))
Info("Awaiting signal ......")
<-done
Info("Except signal, exiting......")
Info("Remove sidecar.lock......")
RemoveLock(d.LockFilePath)
Info("Except signal, exiting ......")
removeLock(d.LockFilePath)
}

// run in backgroud
func StartDaemonProcess(configPath string, serviceType string) {
cmd := &exec.Cmd{
Path: os.Args[0],
Env: []string{"SPECIAL_MARK=ENABLED", "CONF_PATH=" + configPath, "TYPE=" + serviceType},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err := cmd.Start()
if err != nil {
panic(err)
}
os.Exit(0)
}

func StopDaemonProcess(workDir string) {
lockPath := workDir + "/sidecar.lock"
pid := readLock(lockPath)
// if lock exist
if pid != 0 {
proc, _ := os.FindProcess(pid)
proc.Signal(syscall.SIGINT)
} else {
Error("Now sidecar.lock is not exist, server is stopped")
}
}
Loading

0 comments on commit 8ffb937

Please sign in to comment.