This commit is contained in:
zsx 2018-02-24 17:46:09 +08:00
parent efbf8c7747
commit 9b503ac18e
8 changed files with 226 additions and 84 deletions

View File

@ -1,6 +1,6 @@
GOPATH := $(CURDIR)
all: echo web test
all: echo web
echo:
@go build echo
@ -8,8 +8,8 @@ echo:
web:
@go build web
test:
@go build test
#test:
# @go build test
cl clean:
@rm -f echo web test

View File

@ -1,10 +1,11 @@
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"runtime"
"master"
)
@ -26,18 +27,34 @@ func onClose(conn net.Conn) {
log.Println("---client onClose---")
}
var (
filePath string
listenAddr string
)
func main() {
runtime.GOMAXPROCS(1)
flag.StringVar(&filePath, "c", "dummy.cf", "configure filePath")
flag.StringVar(&listenAddr, "listen", "127.0.0.1:8880", "listen addr in alone running")
flag.Parse()
master.Prepare()
fmt.Printf("filePath=%s, MasterServiceType=%s\r\n", filePath, master.MasterServiceType)
master.OnClose(onClose)
master.OnAccept(onAccept)
if len(os.Args) > 1 && os.Args[1] == "alone" {
if master.Alone {
addrs := make([]string, 1)
if len(os.Args) > 2 {
addrs = append(addrs, os.Args[2])
} else {
addrs = append(addrs, "127.0.0.1:8880")
if len(listenAddr) == 0 {
panic("listenAddr null")
}
addrs = append(addrs, listenAddr)
fmt.Printf("listen:")
for _, addr := range addrs {
fmt.Printf(" %s", addr)

View File

@ -4,6 +4,7 @@ import (
"bufio"
"io"
"os"
"strconv"
"strings"
)
@ -66,10 +67,36 @@ func (c *Config) InitConfig(path string) {
}
}
func (c Config) Get(name string) string {
func (c Config) GetString(name string) string {
val, found := c.Entries[name]
if !found {
return ""
}
return val
}
func (c Config) GetInt(name string) int {
val, found := c.Entries[name]
if !found {
return 0
}
n, err := strconv.Atoi(val)
if err != nil {
return 0
} else {
return n
}
}
func (c Config) GetBool(name string) bool {
val, found := c.Entries[name]
if !found {
return false
}
n, err := strconv.Atoi(val)
if err != nil {
return false
} else {
return n != 0
}
}

View File

@ -67,7 +67,7 @@ func OnClose(handler CloseFunc) {
}
func NetStart(addrs []string) {
prepare()
Prepare()
if preJailHandler != nil {
preJailHandler()

View File

@ -1,6 +1,8 @@
package master
import (
"flag"
"fmt"
"log"
"net"
"os"
@ -38,59 +40,100 @@ var (
connCount int = 0
connMutex sync.RWMutex
stopping bool = false
waitExit int = 10
prepareCalled bool = false
)
// from configure file of the app
var (
logPath string
username string
masterArgs string
rootDir string
MasterService string
MasterLogPath string
MasterOwner string
MasterArgs string
AppRootDir string
AppUseLimit int = 0
AppIdleLimit int = 0
AppQuickAbort bool = false
AppWaitLimit int = 10
AppAccessAllow string = "all"
)
// from command args
var (
MasterConfigure string
MasterServiceName string
MasterServiceType string
MasterVerbose bool
MasterUnprivileged bool
// MasterChroot bool
MasterSocketCount int = 1
Alone bool
)
// set the max opened file handles for current process which let
// the process can handle more connections.
func setOpenMax() {
var rlim syscall.Rlimit
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
fmt.Println("get rlimit error: " + err.Error())
return
}
if rlim.Max <= 0 {
rlim.Max = 100000
}
rlim.Cur = rlim.Max
err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim)
if err != nil {
fmt.Println("set rlimit error: " + err.Error())
}
}
// init the command args come from acl_master; the application should call
// flag.Parse() in its main function!
func initFlags() {
flag.StringVar(&MasterConfigure, "f", "", "app configure file")
flag.StringVar(&MasterServiceName, "n", "", "app service name")
flag.StringVar(&MasterServiceType, "t", "sock", "app service type")
flag.BoolVar(&Alone, "alone", false, "stand alone running")
flag.BoolVar(&MasterVerbose, "v", false, "app verbose")
flag.BoolVar(&MasterUnprivileged, "u", false, "app unprivileged")
// flag.BoolVar(&MasterChroot, "c", false, "app chroot")
flag.IntVar(&MasterSocketCount, "s", 1, "listen fd count")
}
func init() {
initFlags()
setOpenMax()
}
func parseArgs() {
/*
flag.IntVar(&listenFdCount, "s", 1, "listen fd count")
flag.StringVar(&confPath, "f", "", "configure path")
flag.StringVar(&sockType, "t", "sock", "socket type")
flag.StringVar(&services, "n", "", "master services")
flag.BoolVar(&privilege, "u", false, "running privilege")
flag.BoolVar(&verbose, "v", false, "debug verbose")
flag.BoolVar(&chrootOn, "c", false, "chroot dir")
flag.Parse()
*/
var n = len(os.Args)
for i := 0; i < n; i++ {
switch os.Args[i] {
case "-s":
i++
if i >= n {
break
}
listenFdCount, _ = strconv.Atoi(os.Args[i])
if listenFdCount <= 0 {
listenFdCount = 1
if i < n {
listenFdCount, _ = strconv.Atoi(os.Args[i])
if listenFdCount <= 0 {
listenFdCount = 1
}
}
case "-f":
i++
if i >= n {
break
if i < n {
confPath = os.Args[i]
}
confPath = os.Args[i]
case "-t":
i++
if i >= n {
break
if i < n {
sockType = os.Args[i]
}
sockType = os.Args[i]
case "-n":
i++
if i >= n {
break
if i < n {
services = os.Args[i]
}
services = os.Args[i]
case "-u":
privilege = true
case "-v":
@ -104,39 +147,54 @@ func parseArgs() {
listenFdCount, sockType, services)
}
func prepare() {
// this function can be called automatically in net_service.go or
// web_service.go to load configure, and it can also be canned in appliction's
// main function
func Prepare() {
if prepareCalled {
return
} else {
prepareCalled = true
}
parseArgs()
conf := new(Config)
conf.InitConfig(confPath)
logPath = conf.Get("master_log")
if len(logPath) > 0 {
f, err := os.OpenFile(logPath,
os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
MasterLogPath = conf.GetString("master_log")
if len(MasterLogPath) > 0 {
f, err := os.OpenFile(MasterLogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
log.Println("OpenFile error", err)
fmt.Printf("OpenFile %s error %s", MasterLogPath, err)
} else {
log.SetOutput(f)
//log.SetOutput(io.MultiWriter(os.Stderr, f))
}
}
masterArgs = conf.Get("master_args")
username = conf.Get("fiber_owner")
rootDir = conf.Get("fiber_queue_dir")
MasterService = conf.GetString("master_service")
MasterOwner = conf.GetString("master_owner")
MasterArgs = conf.GetString("master_args")
log.Printf("Args: %s\r\n", masterArgs)
AppRootDir = conf.GetString("app_queue_dir")
AppUseLimit = conf.GetInt("app_use_limit")
AppIdleLimit = conf.GetInt("app_idle_limit")
AppQuickAbort = conf.GetBool("app_quick_abort")
AppWaitLimit = conf.GetInt("app_wait_limit")
AppAccessAllow = conf.GetString("app_access_allow")
log.Printf("Args: %s, AppAccessAllow: %s\r\n", MasterArgs, AppAccessAllow)
}
func chroot() {
if len(masterArgs) == 0 || !privilege || len(username) == 0 {
if len(MasterArgs) == 0 || !privilege || len(MasterOwner) == 0 {
return
}
user, err := user.Lookup(username)
user, err := user.Lookup(MasterOwner)
if err != nil {
log.Printf("Lookup %s error %s", username, err)
log.Printf("Lookup %s error %s", MasterOwner, err)
} else {
gid, err := strconv.Atoi(user.Gid)
if err != nil {
@ -157,12 +215,12 @@ func chroot() {
}
}
if chrootOn && len(rootDir) > 0 {
err := syscall.Chroot(rootDir)
if chrootOn && len(AppRootDir) > 0 {
err := syscall.Chroot(AppRootDir)
if err != nil {
log.Printf("Chroot error %s, path %s", err, rootDir)
log.Printf("Chroot error %s, path %s", err, AppRootDir)
} else {
log.Printf("Chroot ok, path %s", rootDir)
log.Printf("Chroot ok, path %s", AppRootDir)
err := syscall.Chdir("/")
if err != nil {
log.Printf("Chdir error %s", err)
@ -173,48 +231,56 @@ func chroot() {
}
}
// In run alone mode, the application should give the listening addrs and call
// this function to listen the given addrs
func getListenersByAddrs(addrs []string) []*net.Listener {
listeners := []*net.Listener(nil)
for _, addr := range addrs {
ln, err := net.Listen("tcp", addr)
if err != nil {
panic("listen error")
panic(fmt.Sprintf("listen error=\"%s\", addr=%s", err, addr))
}
listeners = append(listeners, &ln)
}
return listeners
}
// In acl_master daemon running mode, this function will be called for init
// the listener handles.
func getListeners() []*net.Listener {
listeners := []*net.Listener(nil)
for fd := listenFdStart; fd < listenFdStart+listenFdCount; fd++ {
file := os.NewFile(uintptr(fd), "one listenfd")
file := os.NewFile(uintptr(fd), "open one listenfd")
ln, err := net.FileListener(file)
if err != nil {
log.Println("create FileListener error", err)
if err == nil {
listeners = append(listeners, &ln)
log.Printf("add fd: %d", fd)
continue
}
listeners = append(listeners, &ln)
log.Printf("add fd: %d", fd)
file.Close()
log.Println(fmt.Sprintf("create FileListener error=\"%s\", fd=%d", err, fd))
}
return listeners
}
// monitor the PIPE IPC between the current process and acl_master,
// when acl_master close thePIPE, the current process should exit after
// which has handled all its tasks
func monitorMaster(listeners []*net.Listener,
onStopHandler func(), stopHandler func(bool)) {
file := os.NewFile(uintptr(stateFd), "")
conn, err1 := net.FileConn(file)
if err1 != nil {
log.Println("FileConn error", err1)
conn, err := net.FileConn(file)
if err != nil {
log.Println("FileConn error", err)
}
log.Println("waiting master exiting ...")
buf := make([]byte, 1024)
_, err2 := conn.Read(buf)
if err2 != nil {
log.Println("disconnected from master", err2)
_, err = conn.Read(buf)
if err != nil {
log.Println("disconnected from master", err)
}
var n, i int
@ -239,13 +305,14 @@ func monitorMaster(listeners []*net.Listener,
connMutex.RUnlock()
break
}
n = connCount
connMutex.RUnlock()
time.Sleep(time.Second) // sleep 1 second
i++
log.Printf("exiting, clients=%d, sleep=%d seconds", n, i)
if waitExit > 0 && i >= waitExit {
log.Printf("waiting too long >= %d", waitExit)
if AppWaitLimit > 0 && i >= AppWaitLimit {
log.Printf("waiting too long >= %d", AppWaitLimit)
break
}
}

View File

@ -23,7 +23,7 @@ func webServ(ln net.Listener, daemon bool) {
}
func WebStart(addrs []string) {
prepare()
Prepare()
if preJailHandler != nil {
preJailHandler()

View File

@ -1,9 +1,9 @@
package main
import (
"flag"
"fmt"
"net/http"
"os"
"master"
)
@ -15,17 +15,28 @@ func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!\r\n")
}
var (
filePath string
listenAddr string
)
func main() {
flag.StringVar(&filePath, "c", "dummy.cf", "configure filePath")
flag.StringVar(&listenAddr, "listen", "127.0.0.1:8880", "listen addr in alone running")
flag.Parse()
master.Prepare()
http.HandleFunc("/", handler)
if len(os.Args) > 1 && os.Args[1] == "alone" {
if master.Alone {
addrs := make([]string, 1)
if len(os.Args) > 2 {
addrs = append(addrs, os.Args[2])
} else {
addrs = append(addrs, "127.0.0.1:8880")
if len(listenAddr) == 0 {
panic("listenAddr null")
}
addrs = append(addrs, listenAddr)
fmt.Printf("listen:")
for _, addr := range addrs {
fmt.Printf(" %s", addr)

View File

@ -17,8 +17,7 @@ One advanced C/C++ library for Linux/Mac/FreeBSD/Solaris(x86)/Windows/Android/IO
%package -n acl-master
Summary: acl master framework
Release: 78
Summary: acl master framework
License: IBM
Group: System Environment/Tools
Requires(post): /sbin/ldconfig
@ -27,6 +26,14 @@ Requires(postun): /sbin/ldconfig
%description -n acl-master
acl master framework
%package -n acl-tools
Summary: acl tools
Release: 78
License: IBM
Requires: acl-master
%description -n acl-tools
acl tools
%prep
%setup -q
@ -80,8 +87,21 @@ fi
%files -n acl-master
%defattr(-,root,root)
/opt/soft
/opt/soft/acl-master/conf/main.cf
/opt/soft/acl-master/conf/service/samples
/opt/soft/acl-master/libexec/acl_master
/opt/soft/acl-master/sbin
/opt/soft/acl-master/sh
/opt/soft/acl-master/var
/opt/soft/services/acl-master.json
/etc/init.d/master
%exclude /opt/soft/acl-master/conf/service/master_*
%files -n acl-tools
%defattr(-,root,root)
/opt/soft/acl-master/bin/master_ctl
/opt/soft/acl-master/conf/service/master_*
/opt/soft/acl-master/libexec/master_*
%changelog