some windows fixes
This commit is contained in:
parent
196fdee7ac
commit
fa6d7afa05
18
README.md
18
README.md
|
@ -15,3 +15,21 @@ serviceman install --user ./foo-app -- -c ./
|
||||||
```bash
|
```bash
|
||||||
serviceman install --user /usr/local/bin/node ./whatever.js -- -c ./
|
serviceman install --user /usr/local/bin/node ./whatever.js -- -c ./
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
serviceman run --config conf.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"interpreter": "/Program Files (x86)/node/node.exe",
|
||||||
|
"exec": "/Users/aj/demo/demo.js",
|
||||||
|
"argv": ["--foo", "bar", "--baz", "qux"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate -mod=vendor ./...
|
||||||
|
go build -mod=vendor -ldflags "-H=windowsgui"
|
||||||
|
.\\go-serviceman node ./demo.js -- --foo bar --baz qux
|
||||||
|
```
|
|
@ -5,8 +5,8 @@ package installer
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/go-serviceman/service"
|
||||||
)
|
)
|
||||||
|
@ -42,26 +42,18 @@ func Install(c *service.Service) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if we suspect that the current user (or process) will be able
|
// IsPrivileged returns true if we suspect that the current user (or process) will be able
|
||||||
// to write to system folders, bind to privileged ports, and otherwise
|
// to write to system folders, bind to privileged ports, and otherwise
|
||||||
// successfully run a system service.
|
// successfully run a system service.
|
||||||
func IsPrivileged() bool {
|
func IsPrivileged() bool {
|
||||||
return isPrivileged()
|
return isPrivileged()
|
||||||
}
|
}
|
||||||
|
|
||||||
func WhereIs(exec string) (string, error) {
|
// WhereIs uses exec.LookPath to return an absolute filepath with forward slashes
|
||||||
// TODO use exec.LookPath instead
|
func WhereIs(exe string) (string, error) {
|
||||||
exec = filepath.ToSlash(exec)
|
exepath, err := exec.LookPath(exe)
|
||||||
if strings.Contains(exec, "/") {
|
if nil != err {
|
||||||
// it's a path (so we don't allow filenames with slashes)
|
return "", err
|
||||||
stat, err := os.Stat(exec)
|
|
||||||
if nil != err {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if stat.IsDir() {
|
|
||||||
return "", fmt.Errorf("'%s' is not an executable file", exec)
|
|
||||||
}
|
|
||||||
return filepath.Abs(exec)
|
|
||||||
}
|
}
|
||||||
return whereIs(exec)
|
return filepath.Abs(filepath.ToSlash(exepath))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package installer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func whereIs(exe string) (string, error) {
|
|
||||||
// TODO use exec.LookPath instead
|
|
||||||
cmd := exec.Command("command", "-v", exe)
|
|
||||||
out, err := cmd.Output()
|
|
||||||
if nil != err {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(out)), nil
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -77,24 +76,21 @@ func install(c *service.Service) error {
|
||||||
// it can be "the main thing"
|
// it can be "the main thing"
|
||||||
bin = exec
|
bin = exec
|
||||||
}
|
}
|
||||||
if 0 != len(args) {
|
|
||||||
// On Windows the /c acts kinda like -- does on *nix,
|
|
||||||
// at least for commands in the registry that have arguments
|
|
||||||
setArgs = ` /c `
|
|
||||||
}
|
|
||||||
|
|
||||||
// The final string ends up looking something like one of these:
|
// The final string ends up looking something like one of these:
|
||||||
// "C:\Users\aj\.local\opt\appname\appname.js /c -p 8080"
|
// `"C:\Users\aj\.local\opt\appname\appname.js" -p 8080`
|
||||||
// "C:\Program Files (x64)\nodejs\node.exe /c C:\Users\aj\.local\opt\appname\appname.js -p 8080"
|
// `"C:\Program Files (x64)\nodejs\node.exe" C:\Users\aj\.local\opt\appname\appname.js -p 8080`
|
||||||
regSZ := bin + setArgs + strings.Join(c.Argv, " ")
|
regSZ := bin + setArgs + strings.Join(c.Argv, " ")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
regSZ := fmt.Sprintf("%s /c %s", args[0], strings.Join(args[1:], " "))
|
regSZ := fmt.Sprintf(`"%s" %s`, args[0], strings.Join(args[1:], " "))
|
||||||
if len(regSZ) > 260 {
|
if len(regSZ) > 260 {
|
||||||
return fmt.Errorf("data value is too long for registry entry")
|
return fmt.Errorf("data value is too long for registry entry")
|
||||||
}
|
}
|
||||||
fmt.Println("Set Registry Key:")
|
// In order for a windows gui program to not show a console,
|
||||||
fmt.Println(autorunKey, c.Title, regSZ)
|
// it has to not output any messages?
|
||||||
|
//fmt.Println("Set Registry Key:")
|
||||||
|
//fmt.Println(autorunKey, c.Title, regSZ)
|
||||||
k.SetStringValue(c.Title, regSZ)
|
k.SetStringValue(c.Title, regSZ)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -108,7 +104,7 @@ func installServiceman(c *service.Service) ([]string, error) {
|
||||||
// TODO support service level services (which probably wouldn't need serviceman)
|
// TODO support service level services (which probably wouldn't need serviceman)
|
||||||
smdir = filepath.Join(c.Home, ".local", smdir)
|
smdir = filepath.Join(c.Home, ".local", smdir)
|
||||||
// for now we'll scope the runner to the name of the application
|
// for now we'll scope the runner to the name of the application
|
||||||
smbin := filepath.Join(smdir, `bin\serviceman.`+c.Name)
|
smbin := filepath.Join(smdir, `bin\serviceman.`+c.Name+`.exe`)
|
||||||
|
|
||||||
if smbin != self {
|
if smbin != self {
|
||||||
err := os.MkdirAll(filepath.Dir(smbin), 0755)
|
err := os.MkdirAll(filepath.Dir(smbin), 0755)
|
||||||
|
@ -148,13 +144,3 @@ func installServiceman(c *service.Service) ([]string, error) {
|
||||||
conffile,
|
conffile,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func whereIs(exe string) (string, error) {
|
|
||||||
// TODO use exec.LookPath instead
|
|
||||||
cmd := exec.Command("where.exe", exe)
|
|
||||||
out, err := cmd.Output()
|
|
||||||
if nil != err {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(out)), nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,11 +5,15 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rootprojects.org/root/go-serviceman/service"
|
"git.rootprojects.org/root/go-serviceman/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Filled in on init by runner_windows.go
|
||||||
|
var shellArgs = []string{}
|
||||||
|
|
||||||
// Notes on spawning a child process
|
// Notes on spawning a child process
|
||||||
// https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4
|
// https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4
|
||||||
|
|
||||||
|
@ -30,11 +34,17 @@ func Run(conf *service.Service) {
|
||||||
}
|
}
|
||||||
args = append(args, conf.Argv...)
|
args = append(args, conf.Argv...)
|
||||||
|
|
||||||
|
if !conf.System && 0 != len(shellArgs) {
|
||||||
|
nargs := append(shellArgs[1:], binpath)
|
||||||
|
args = append(nargs, args...)
|
||||||
|
binpath = shellArgs[0]
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// setup the log
|
// setup the log
|
||||||
lf, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
lf, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "Could not open log file %q\n", logfile)
|
fmt.Fprintf(os.Stderr, "[%s] Could not open log file %q\n", time.Now(), logfile)
|
||||||
lf = os.Stderr
|
lf = os.Stderr
|
||||||
} else {
|
} else {
|
||||||
defer lf.Close()
|
defer lf.Close()
|
||||||
|
@ -42,6 +52,8 @@ func Run(conf *service.Service) {
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
cmd := exec.Command(binpath, args...)
|
cmd := exec.Command(binpath, args...)
|
||||||
|
fmt.Fprintf(lf, "[%s] Starting %q %s \n", time.Now(), binpath, strings.Join(args, " "))
|
||||||
|
|
||||||
cmd.Stdin = nil
|
cmd.Stdin = nil
|
||||||
cmd.Stdout = lf
|
cmd.Stdout = lf
|
||||||
cmd.Stderr = lf
|
cmd.Stderr = lf
|
||||||
|
@ -50,20 +62,18 @@ func Run(conf *service.Service) {
|
||||||
}
|
}
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(lf, "Could not start %q process: %s\n", conf.Name, err)
|
fmt.Fprintf(lf, "[%s] Could not start %q process: %s\n", time.Now(), conf.Name, err)
|
||||||
} else {
|
} else {
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(lf, "Process %q failed with error: %s\n", conf.Name, err)
|
fmt.Fprintf(lf, "[%s] Process %q failed with error: %s\n", time.Now(), conf.Name, err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(lf, "Process %q exited cleanly\n", conf.Name)
|
fmt.Fprintf(lf, "[%s] Process %q exited cleanly\n", time.Now(), conf.Name)
|
||||||
fmt.Printf("Process %q exited cleanly\n", conf.Name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this is a oneshot... so it is
|
// if this is a oneshot... so it is
|
||||||
if !conf.Restart {
|
if !conf.Restart {
|
||||||
fmt.Printf("Not restarting %q because `restart` set to `false`\n", conf.Name)
|
|
||||||
fmt.Fprintf(lf, "Not restarting %q because `restart` set to `false`\n", conf.Name)
|
fmt.Fprintf(lf, "Not restarting %q because `restart` set to `false`\n", conf.Name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package runner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmd, _ := exec.LookPath("cmd.exe")
|
||||||
|
if "" != cmd {
|
||||||
|
shellArgs = []string{cmd, "/c"}
|
||||||
|
}
|
||||||
|
}
|
|
@ -178,7 +178,7 @@ func run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Normalize(false)
|
s.Normalize(false)
|
||||||
fmt.Fprintf(os.Stdout, "Logdir: %s\n", s.Logdir)
|
//fmt.Fprintf(os.Stdout, "Logdir: %s\n", s.Logdir)
|
||||||
err = os.MkdirAll(s.Logdir, 0755)
|
err = os.MkdirAll(s.Logdir, 0755)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
|
@ -186,7 +186,7 @@ func run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !daemonize {
|
if !daemonize {
|
||||||
fmt.Fprintf(os.Stdout, "Running %s %s %s\n", s.Interpreter, s.Exec, strings.Join(s.Argv, " "))
|
//fmt.Fprintf(os.Stdout, "Running %s %s %s\n", s.Interpreter, s.Exec, strings.Join(s.Argv, " "))
|
||||||
runner.Run(s)
|
runner.Run(s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue