mirror of
https://gitee.com/johng/gf
synced 2026-06-27 01:43:33 +08:00
gfile增加IsExecutable方法
This commit is contained in:
@ -23,10 +23,12 @@ import (
|
||||
"time"
|
||||
"runtime"
|
||||
"bytes"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
const (
|
||||
gADMIN_ACTION_INTERVAL_LIMIT = 2000 // (毫秒)服务开启后允许执行管理操作的间隔限制
|
||||
gADMIN_ACTION_NONE = 0
|
||||
gADMIN_ACTION_RESTARTING = 1
|
||||
gADMIN_ACTION_SHUTINGDOWN = 2
|
||||
gADMIN_ACTION_RELOAD_ENVKEY = "GF_SERVER_RELOAD"
|
||||
@ -68,7 +70,16 @@ func (p *utilAdmin) Index(r *Request) {
|
||||
// 服务重启
|
||||
func (p *utilAdmin) Restart(r *Request) {
|
||||
var err error = nil
|
||||
// 必须检查可执行文件的权限
|
||||
path := r.GetQueryString("newExeFilePath")
|
||||
if path == "" {
|
||||
path = os.Args[0]
|
||||
}
|
||||
if !gfile.IsExecutable(path) {
|
||||
r.Response.Writef("file '%s' is not executable", path)
|
||||
return
|
||||
}
|
||||
// 执行重启操作
|
||||
if len(path) > 0 {
|
||||
err = r.Server.Restart(path)
|
||||
} else {
|
||||
@ -112,8 +123,7 @@ func (s *Server) Restart(newExeFilePath...string) error {
|
||||
if err := s.checkActionFrequence(); err != nil {
|
||||
return err
|
||||
}
|
||||
restartWebServers(false, newExeFilePath...)
|
||||
return nil
|
||||
return restartWebServers(false, newExeFilePath...)
|
||||
}
|
||||
|
||||
// 关闭Web Server
|
||||
@ -153,7 +163,7 @@ func (s *Server) checkActionStatus() error {
|
||||
}
|
||||
|
||||
// 平滑重启:创建一个子进程,通过环境变量传参
|
||||
func forkReloadProcess(newExeFilePath...string) {
|
||||
func forkReloadProcess(newExeFilePath...string) error {
|
||||
path := os.Args[0]
|
||||
if len(newExeFilePath) > 0 {
|
||||
path = newExeFilePath[0]
|
||||
@ -184,11 +194,13 @@ func forkReloadProcess(newExeFilePath...string) {
|
||||
p.Env = append(p.Env, gADMIN_ACTION_RELOAD_ENVKEY + "=" + string(buffer))
|
||||
if _, err := p.Start(); err != nil {
|
||||
glog.Errorfln("%d: fork process failed, error:%s, %s", gproc.Pid(), err.Error(), string(buffer))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 完整重启:创建一个新的子进程
|
||||
func forkRestartProcess(newExeFilePath...string) {
|
||||
func forkRestartProcess(newExeFilePath...string) error {
|
||||
path := os.Args[0]
|
||||
if len(newExeFilePath) > 0 {
|
||||
path = newExeFilePath[0]
|
||||
@ -200,7 +212,9 @@ func forkRestartProcess(newExeFilePath...string) {
|
||||
p := gproc.NewProcess(path, os.Args, env)
|
||||
if _, err := p.Start(); err != nil {
|
||||
glog.Errorfln("%d: fork process failed, error:%s", gproc.Pid(), err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取所有Web Server的文件描述符map
|
||||
@ -231,24 +245,30 @@ func bufferToServerFdMap(buffer []byte) map[string]listenerFdMap {
|
||||
}
|
||||
|
||||
// Web Server重启
|
||||
func restartWebServers(isSignal bool, newExeFilePath...string) {
|
||||
func restartWebServers(isSignal bool, newExeFilePath...string) error {
|
||||
serverProcessStatus.Set(gADMIN_ACTION_RESTARTING)
|
||||
glog.Printfln("%d: server restarting", gproc.Pid())
|
||||
if runtime.GOOS == "windows" {
|
||||
if isSignal {
|
||||
// 在终端信号下,立即执行重启操作
|
||||
forcedlyCloseWebServers()
|
||||
forkRestartProcess(newExeFilePath...)
|
||||
} else {
|
||||
// 非终端信号下,异步1秒后再执行重启,目的是让接口能够正确返回结果,否则接口会报错(因为web server关闭了)
|
||||
gtime.SetTimeout(time.Second, func() {
|
||||
// 非终端信号下,异步3秒后再执行重启,目的是让接口能够正确返回结果,否则接口会报错(因为web server关闭了)
|
||||
gtime.SetTimeout(3*time.Second, func() {
|
||||
forcedlyCloseWebServers()
|
||||
forkRestartProcess(newExeFilePath...)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
forkReloadProcess(newExeFilePath...)
|
||||
if err := forkReloadProcess(newExeFilePath...); err != nil {
|
||||
glog.Printfln("%d: server restarts failed", gproc.Pid())
|
||||
serverProcessStatus.Set(gADMIN_ACTION_NONE)
|
||||
return err
|
||||
} else {
|
||||
glog.Printfln("%d: server restarting", gproc.Pid())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Web Server关闭服务
|
||||
|
||||
@ -285,6 +285,20 @@ func IsWritable(path string) bool {
|
||||
return result
|
||||
}
|
||||
|
||||
// 文件是否可执行
|
||||
func IsExecutable(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil || info.IsDir() {
|
||||
return false
|
||||
}
|
||||
// 73: 000 001 001 001
|
||||
flag := info.Mode().Perm() & os.FileMode(73)
|
||||
if uint32(flag) == uint32(73) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 修改文件/目录权限
|
||||
func Chmod(path string, mode os.FileMode) error {
|
||||
return os.Chmod(path, mode)
|
||||
|
||||
Reference in New Issue
Block a user