package main import ( "fmt" "log" "net" "os" "os/signal" "sync" "syscall" "github.com/gofrs/flock" "github.com/spf13/pflag" ) var ( wg = sync.WaitGroup{} helpFlag = pflag.BoolP("help", "p", false, "show help") ) func main() { socketPath := "/tmp/rsyslog.sock" pflag.Parse() if *helpFlag { fmt.Printf("%s: \nObtain SSHD logs from rsyslog, record them, and provide query services.\n", os.Args[0]) fmt.Printf("You need to forward the sshd logs to the Unix socket(%s) via rsyslog.\n", socketPath) fmt.Printf("You can access the Unix socket(%s) to obtain online user information.\n", GIN_SOCK_PATH) fmt.Println("such as: curl -s --unix-socket /tmp//tmp/sshd-tool.sock http://localhost/user | jq") return } fileLock := flock.New("/var/lock/sshd-tool.lock", flock.SetPermissions(0644)) l, err := fileLock.TryLock() if err != nil { log.Fatalf("error lock file /var/lock/sshd-tool.lock, %v", err) } if !l { log.Fatalf("can't lock /var/lock/sshd-tool.lock, Perhaps an instance is already running.") } InitSSH() serverListener := InitGin() err = os.RemoveAll(socketPath) if err != nil { log.Fatalf("error delete %s: %v", socketPath, err) } conn, err := net.ListenPacket("unixgram", socketPath) if err != nil { log.Fatalf("listen unix socket %s failed: %s", socketPath, err.Error()) } err = os.Chmod(socketPath, 0666) if err != nil { log.Fatalf("chmod 666 %s failed: %v", socketPath, err) } sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) wg.Add(1) go func(wg *sync.WaitGroup) { select { case <-sigChan: conn.Close() serverListener.Close() os.Remove(socketPath) os.Remove(GIN_SOCK_PATH) fileLock.Unlock() case <-globalCtx.Done(): conn.Close() serverListener.Close() os.Remove(socketPath) os.Remove(GIN_SOCK_PATH) fileLock.Unlock() } wg.Done() }(&wg) buffer := make([]byte, 16384) for { n, _, err := conn.ReadFrom(buffer) if err != nil { globalCancelFunc() break } go ParseSSHLog(string(buffer[:n])) } wg.Wait() }