some windows fixes
This commit is contained in:
		
							父節點
							
								
									196fdee7ac
								
							
						
					
					
						當前提交
						fa6d7afa05
					
				
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							| @ -15,3 +15,21 @@ serviceman install --user ./foo-app -- -c ./ | ||||
| ```bash | ||||
| 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 ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"git.rootprojects.org/root/go-serviceman/service" | ||||
| ) | ||||
| @ -42,26 +42,18 @@ func Install(c *service.Service) error { | ||||
| 	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 | ||||
| // successfully run a system service. | ||||
| func IsPrivileged() bool { | ||||
| 	return isPrivileged() | ||||
| } | ||||
| 
 | ||||
| func WhereIs(exec string) (string, error) { | ||||
| 	// TODO use exec.LookPath instead | ||||
| 	exec = filepath.ToSlash(exec) | ||||
| 	if strings.Contains(exec, "/") { | ||||
| 		// it's a path (so we don't allow filenames with slashes) | ||||
| 		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) | ||||
| // WhereIs uses exec.LookPath to return an absolute filepath with forward slashes | ||||
| func WhereIs(exe string) (string, error) { | ||||
| 	exepath, err := exec.LookPath(exe) | ||||
| 	if nil != err { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	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" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| @ -77,24 +76,21 @@ func install(c *service.Service) error { | ||||
| 			// it can be "the main thing" | ||||
| 			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: | ||||
| 		// "C:\Users\aj\.local\opt\appname\appname.js /c -p 8080" | ||||
| 		// "C:\Program Files (x64)\nodejs\node.exe /c C:\Users\aj\.local\opt\appname\appname.js -p 8080" | ||||
| 		// `"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 := 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 { | ||||
| 		return fmt.Errorf("data value is too long for registry entry") | ||||
| 	} | ||||
| 	fmt.Println("Set Registry Key:") | ||||
| 	fmt.Println(autorunKey, c.Title, regSZ) | ||||
| 	// In order for a windows gui program to not show a console, | ||||
| 	// it has to not output any messages? | ||||
| 	//fmt.Println("Set Registry Key:") | ||||
| 	//fmt.Println(autorunKey, c.Title, regSZ) | ||||
| 	k.SetStringValue(c.Title, regSZ) | ||||
| 
 | ||||
| 	return nil | ||||
| @ -108,7 +104,7 @@ func installServiceman(c *service.Service) ([]string, error) { | ||||
| 	// TODO support service level services (which probably wouldn't need serviceman) | ||||
| 	smdir = filepath.Join(c.Home, ".local", smdir) | ||||
| 	// 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 { | ||||
| 		err := os.MkdirAll(filepath.Dir(smbin), 0755) | ||||
| @ -148,13 +144,3 @@ func installServiceman(c *service.Service) ([]string, error) { | ||||
| 		conffile, | ||||
| 	}, 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/exec" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"git.rootprojects.org/root/go-serviceman/service" | ||||
| ) | ||||
| 
 | ||||
| // Filled in on init by runner_windows.go | ||||
| var shellArgs = []string{} | ||||
| 
 | ||||
| // Notes on spawning a child process | ||||
| // https://groups.google.com/forum/#!topic/golang-nuts/shST-SDqIp4 | ||||
| 
 | ||||
| @ -30,11 +34,17 @@ func Run(conf *service.Service) { | ||||
| 	} | ||||
| 	args = append(args, conf.Argv...) | ||||
| 
 | ||||
| 	if !conf.System && 0 != len(shellArgs) { | ||||
| 		nargs := append(shellArgs[1:], binpath) | ||||
| 		args = append(nargs, args...) | ||||
| 		binpath = shellArgs[0] | ||||
| 	} | ||||
| 
 | ||||
| 	for { | ||||
| 		// setup the log | ||||
| 		lf, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) | ||||
| 		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 | ||||
| 		} else { | ||||
| 			defer lf.Close() | ||||
| @ -42,6 +52,8 @@ func Run(conf *service.Service) { | ||||
| 
 | ||||
| 		start := time.Now() | ||||
| 		cmd := exec.Command(binpath, args...) | ||||
| 		fmt.Fprintf(lf, "[%s] Starting %q %s \n", time.Now(), binpath, strings.Join(args, " ")) | ||||
| 
 | ||||
| 		cmd.Stdin = nil | ||||
| 		cmd.Stdout = lf | ||||
| 		cmd.Stderr = lf | ||||
| @ -50,20 +62,18 @@ func Run(conf *service.Service) { | ||||
| 		} | ||||
| 		err = cmd.Start() | ||||
| 		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 { | ||||
| 			err = cmd.Wait() | ||||
| 			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 { | ||||
| 				fmt.Fprintf(lf, "Process %q exited cleanly\n", conf.Name) | ||||
| 				fmt.Printf("Process %q exited cleanly\n", conf.Name) | ||||
| 				fmt.Fprintf(lf, "[%s] Process %q exited cleanly\n", time.Now(), conf.Name) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// if this is a oneshot... so it is | ||||
| 		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) | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
							
								
								
									
										12
									
								
								runner/runner_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								runner/runner_windows.go
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
| 	fmt.Fprintf(os.Stdout, "Logdir: %s\n", s.Logdir) | ||||
| 	//fmt.Fprintf(os.Stdout, "Logdir: %s\n", s.Logdir) | ||||
| 	err = os.MkdirAll(s.Logdir, 0755) | ||||
| 	if nil != err { | ||||
| 		fmt.Fprintf(os.Stderr, "%s\n", err) | ||||
| @ -186,7 +186,7 @@ func run() { | ||||
| 	} | ||||
| 
 | ||||
| 	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) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user