func startCmd(cmdName string, args ...string) (*exec.Cmd, error) { var err error lvl := syslog.Priority(stdoutLevel) | syslog.Priority(facility) stdoutLog, err = syslog.New(lvl, tag) if err != nil { log.Fatalf("Error initializing stdout syslog: %v", err) } lvl = syslog.Priority(stderrLevel) | syslog.Priority(facility) stderrLog, err = syslog.New(lvl, tag) if err != nil { log.Fatalf("Error initializing stderr syslog: %v", err) } cmd := exec.Command(cmdName, args...) cmd.Stdin = os.Stdin stdoutPipe, err := cmd.StdoutPipe() if err != nil { log.Fatalf("Error initializing stdout pipe: %v", err) } stderrPipe, err := cmd.StderrPipe() if err != nil { log.Fatalf("Error initializing stderr pipe: %v", err) } wg.Add(2) go logPipe(stdoutLog, stdoutPipe) go logPipe(stderrLog, stderrPipe) return cmd, cmd.Start() }
// newPriority creates a new default priority func (d *DockerLogParser) newPriority(p int) Priority { // The Priority value is calculated by first multiplying the Facility // number by 8 and then adding the numerical value of the Severity. return Priority{ Pri: p, Facility: syslog.Priority(p / 8), Severity: syslog.Priority(p % 8), } }
func parseFacility(facility string) (syslog.Priority, error) { if facility == "" { return syslog.LOG_DAEMON, nil } if syslogFacility, valid := facilities[facility]; valid { return syslogFacility, nil } fInt, err := strconv.Atoi(facility) if err == nil && 0 <= fInt && fInt <= 23 { return syslog.Priority(fInt << 3), nil } return syslog.Priority(0), errors.New("invalid syslog facility") }
func (c *sysLogger) LoadConfig(config map[string]interface{}) error { if level, ok := config["level"]; ok { c.level = level.(int) } else { c.level = LevelDebug } if sysLevel, ok := config["sysLevel"]; ok { c.sysLevel = LocalLevel[sysLevel.(int)] } else { c.sysLevel = syslog.LOG_LOCAL6 } var Flags int if flags, ok := config["flags"]; ok { Flags = flags.(int) } else { Flags = 9 } var err error c.logger, err = syslog.NewLogger(syslog.LOG_NOTICE|syslog.Priority(c.sysLevel), Flags) if err != nil { return errors.New("syslog newLogger error") } return nil }
// SyslogSink returns a sink that outputs to the local syslog daemon. func SyslogSink(p Priority, tag, format string, fields []string) (*syslogSink, error) { prio := syslog.Priority(p) | syslog.LOG_USER w, err := syslog.New(prio, tag) if err != nil { return nil, err } return &syslogSink{w, p, format, fields}, nil }
// NewSyslogOutput returns a TextOutput object that writes to syslog using // the given facility and tag. The log level will be determined by the log // event. func NewSyslogOutput(facility SyslogPriority, tag string) ( TextOutput, error) { w, err := syslog.New(syslog.Priority(facility), tag) if err != nil { return nil, err } return &SyslogOutput{w: w}, nil }
// NewLogger is used to construct a new Syslogger func NewLogger(p Priority, tag string) (Syslogger, error) { priority := syslog.Priority(p) | syslog.LOG_DAEMON l, err := syslog.New(priority, tag) if err != nil { return nil, err } return &builtinLogger{l}, nil }
// establishes the connection to syslog. func (conf *syslogModuleConfig) connectToSyslog( network, raddr string, facility int, tag string) error { facilityName, err := FacilityValueToName(facility) if err != nil { return err } var priority goSyslog.Priority = goSyslog.Priority(facility<<3) | goSyslog.LOG_INFO conf.network = network conf.raddr = raddr conf.facility = facility conf.tag = tag conf.syslogConn, err = goSyslog.Dial(network, raddr, priority, tag) if err != nil { log.Printf("Could not open connection to syslog, reason: " + err.Error()) return err } if conf.syslogConn == nil { log.Printf("Could not retrieve connection to syslog") return fmt.Errorf("Could not retrieve connection to syslog") } conf.syslogConn.Debug( fmt.Sprintf( "rlog syslog (re)connected with facility=%d(%s), tag=\"%s\"", facility, facilityName, tag)) conf.syslogConn.Debug( fmt.Sprintf( "rlog syslog network=\"%s\", raddr=\"%s\", heartBeatFilePath=\"%s\"", network, raddr, conf.heartBeatFilePath)) // FIX: heartbeat for debugging only. if conf.heartBeatFilePath != "" { parentDir, _ := filepath.Split(conf.heartBeatFilePath) if parentDir != "" { var dirMode os.FileMode = 0775 // user/group-only read/write/traverse, world read/traverse err = os.MkdirAll(parentDir, dirMode) if err != nil { return err } } err = conf.writeHeartBeat("Starting heartbeat...", true) if err != nil { return err } } return nil }
func openSyslog(level Priority, prefix string) *log.Logger { logger, err := syslog.NewLogger(syslog.Priority(level), log.Lshortfile) if err != nil { fmt.Println("Error opening syslog: ", err) return nil } logger.SetPrefix(prefix) return logger }
func TestInvalidSeverity(t *testing.T) { fw := &fakeWriter{} writer = fw event.Dispatch(&TestEvent{priority: syslog.Priority(123), message: "log me"}) if fw.message == "log me" { t.Errorf("message was logged despite invalid severity") } }
// NewLogger is used to construct a new Syslogger func NewLogger(p Priority, facility, tag string) (Syslogger, error) { fPriority, err := facilityPriority(facility) if err != nil { return nil, err } priority := syslog.Priority(p) | fPriority l, err := newBuiltin(priority, tag) if err != nil { return nil, err } return &builtinLogger{l}, nil }
// DialLogger is used to construct a new Syslogger that establishes connection to remote syslog server func DialLogger(network, raddr string, p Priority, facility, tag string) (Syslogger, error) { fPriority, err := facilityPriority(facility) if err != nil { return nil, err } priority := syslog.Priority(p) | fPriority l, err := dialBuiltin(network, raddr, priority, tag) if err != nil { return nil, err } return &builtinLogger{l}, nil }
func LogInit(level Priority, prefix string, toSyslog bool, debugSelectors []string) { _log.toSyslog = toSyslog _log.level = syslog.Priority(level) _log.selectors = make(map[string]bool) for _, selector := range debugSelectors { _log.selectors[selector] = true } if _log.toSyslog { for prio := syslog.LOG_EMERG; prio <= syslog.LOG_DEBUG; prio++ { _log.syslog[prio] = openSyslog(prio, prefix) } } else { _log.logger = log.New(os.Stdout, prefix, log.Lshortfile) } }
func lookup(str string) (syslog.Priority, error) { n, err := strconv.ParseInt(str, 64, 0) if err == nil { return syslog.Priority(n), nil } facility, priority := "user", "notice" if i := strings.IndexRune(str, '.'); i > 0 { facility, priority = str[:i], str[i+1:] } else { priority = str } facility = strings.ToLower(facility) priority = strings.ToLower(priority) var p syslog.Priority switch facility { case "kern": p |= syslog.LOG_KERN case "user": p |= syslog.LOG_USER case "mail": p |= syslog.LOG_MAIL case "daemon": p |= syslog.LOG_DAEMON case "auth": p |= syslog.LOG_AUTH case "syslog": p |= syslog.LOG_SYSLOG case "lpr": p |= syslog.LOG_LPR case "news": p |= syslog.LOG_NEWS case "uucp": p |= syslog.LOG_UUCP case "cron": p |= syslog.LOG_CRON case "authpriv": p |= syslog.LOG_AUTHPRIV case "ftp": p |= syslog.LOG_FTP case "local0": p |= syslog.LOG_LOCAL0 case "local1": p |= syslog.LOG_LOCAL1 case "local2": p |= syslog.LOG_LOCAL2 case "local3": p |= syslog.LOG_LOCAL3 case "local4": p |= syslog.LOG_LOCAL4 case "local5": p |= syslog.LOG_LOCAL5 case "local6": p |= syslog.LOG_LOCAL6 case "local7": p |= syslog.LOG_LOCAL7 default: return 0, fmt.Errorf("invalid facility %q", facility) } switch priority { case "emerg": p |= syslog.LOG_EMERG case "alert": p |= syslog.LOG_ALERT case "crit": p |= syslog.LOG_CRIT case "err": p |= syslog.LOG_ERR case "warning": p |= syslog.LOG_WARNING case "notice": p |= syslog.LOG_NOTICE case "info": p |= syslog.LOG_INFO case "debug": p |= syslog.LOG_DEBUG default: return 0, fmt.Errorf("invalid priority %q", priority) } return p, nil }
func NewSyslogFormatter(format string) *SyslogFormatter { hostname, _ := os.Hostname() return &SyslogFormatter{NewPatFormatter(format), os.Getpid(), hostname, os.Args[0], syslog.Priority(1 << 3), DefaultSeverityMap} }
func (l logLevel) String() string { return levelStrings[syslog.Priority(l)&7] }
func (l logFacility) String() string { return facilityStrings[syslog.Priority(l)&^7] }
func main() { flag.Parse() // Set logTarget if *logTarget == "" { logger = log.New(os.Stdout, "LOG ", log.LstdFlags) debugLogger = log.New(os.Stdout, "DEBUG ", log.LstdFlags) } else { u, err := url.Parse(*logTarget) if err != nil { log.Fatalln("fatal: unable to parse logtarget url", err) } query, _ := url.ParseQuery(u.RawQuery) switch { case (u.Scheme == "" || u.Scheme == "file") && u.Path != "": var logFile *os.File fileMode := os.FileMode(*logPermission) _, err = os.Stat(u.Path) if os.IsNotExist(err) { logFile, err = os.Create(u.Path) if err != nil { log.Fatalln("fatal: unable to create log target", err) } err = os.Chmod(u.Path, fileMode) if err != nil { log.Fatalln("fatal: unable to set file permissions", err) } } else { logFile, err = os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND, fileMode) if err != nil { log.Fatalln("fatal: unable to open log target", err) } } defer logFile.Close() logTargetWriter = io.Writer(logFile) // Check if logTarget is writable _, err = logTargetWriter.Write([]byte("")) if err != nil { log.Fatalln("fatal: unable to write to log target") } case strings.HasPrefix(u.Scheme, "syslog"): var syslogLogger *syslog.Writer var tag string priority := int(syslog.LOG_NOTICE | syslog.LOG_LOCAL0) if query["priority"][0] != "" { priority, err = strconv.Atoi(query["priority"][0]) if err != nil { log.Fatalln("fatal: unable to connect to syslog", *logTarget, "err:", err) } } if query["tag"][0] != "" { tag = query["tag"][0] } if u.Host == "" { syslogLogger, err = syslog.New(syslog.Priority(priority), tag) if err != nil { log.Fatalln("fatal: unable to connect to syslog", *logTarget, "err:", err) } } else { schemeParts := strings.Split(u.Scheme, "+") network := "tcp" if len(schemeParts) > 1 { network = schemeParts[1] } _, _, err := net.SplitHostPort(u.Host) if err != nil { u.Host = u.Host + ":514" } syslogLogger, err = syslog.Dial(network, u.Host, syslog.Priority(priority), tag) if err != nil { log.Fatalln("fatal: unable to connect to syslog", *logTarget, "err:", err) } } defer syslogLogger.Close() logTargetWriter = io.Writer(syslogLogger) default: log.Fatalln("fatal: no valid schema:", *logTarget) } logger = log.New(logTargetWriter, "LOG ", log.LstdFlags) debugLogger = log.New(logTargetWriter, "DEBUG ", log.LstdFlags) } // Set log-function based on log level switch *logLevel { case 0: logf = emptyLogf case 2: debugf = debugLogf default: } // Write example log lines logf("log output %s, %d", "string1", 10) debugf("debug output %s, %d", "string1", 10) }
// runMain is a main function which returns programs exit value. func runMain() int { var err error LOG, err = wl.New("goanysync", syslog.Priority(0), wl.DEFAULT_LOG_LEVEL) if err != nil { fmt.Fprintf(os.Stderr, "Error: Logger initialization failed with error: %s\n", err) return 1 } // Check that at least one argument given if len(os.Args) < 2 { LOG.Err("No command given.") return 1 } configFilePath := flag.String("c", "/etc/goanysync.conf", "Config file.") verbose := flag.Bool("v", false, "Be more verbose with console messages.") syslogLogLevel := flag.Int("sl", int(wl.DEFAULT_LOG_LEVEL), "Set syslog log level.") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s %s:\n", os.Args[0], "[options] <command>") fmt.Fprintf(os.Stderr, " Commands:\n") fmt.Fprintf(os.Stderr, " initsync\tReplaces sync directories with symlinks to tmpfs while syncing orginal content there.\n") fmt.Fprintf(os.Stderr, " sync\t\tSyncs content from tmpfs to the backup.\n") fmt.Fprintf(os.Stderr, " unsync\tRestores orginal state of sync directories.\n") fmt.Fprintf(os.Stderr, " check\tChecks if sync was called without unsync before tmpfs was cleared.\n") fmt.Fprintf(os.Stderr, " start\tAlias for running check and initsync.\n") fmt.Fprintf(os.Stderr, " stop\t\tAlias for running sync and unsync.\n") fmt.Fprintf(os.Stderr, " info\t\tGives information about current sync status.\n") fmt.Fprintf(os.Stderr, " Options:\n") flag.PrintDefaults() if *verbose { fmt.Fprintf(os.Stderr, " Log levels:\n") for i := 0; i < len(wl.LOG_LEVELS); i++ { fmt.Fprintf(os.Stderr, " %d: %s\n", i, wl.LOG_LEVELS[syslog.Priority(i)]) } } } flag.Parse() LOG.SetSyslogPriority(syslog.Priority(*syslogLogLevel)) if *verbose { LOG.SetConsoleLogPriority(syslog.LOG_DEBUG) } // Read config file copts, err := ReadConfigFile(*configFilePath) if err != nil { LOG.Err("Config file: %s", err) return 1 } if *verbose { copts.Print() } // For now do not allow synchronous calls at all. // Check that lock files base path if err = checkLockFileDir(path.Dir(copts.lockfile)); err != nil { LOG.Err("Lock file path: %s", err) return 1 } // Locking to prevent synchronous operations for ok, err := getLock(copts.lockfile); !ok; ok, err = getLock(copts.lockfile) { if err != nil { LOG.Err("Lock file: %s", err) return 1 } // TODO: specify max wait time // TODO: use inotify when go provides an interface for it time.Sleep(time.Millisecond * 100) } // If os.Exit() is called remember to remove the lock file, manually. defer releaseLock(copts.lockfile) switch flag.Arg(0) { case "info": info(copts) case "check": checkAndFix(copts.tmpfsPath, &copts.syncPaths) case "initsync": if err := initSync(copts.tmpfsPath, &copts.syncPaths, copts.syncerBin); err != nil { LOG.Err(err.Error()) return 1 } case "sync": sync(copts.tmpfsPath, &copts.syncPaths, copts.syncerBin) case "unsync": unsync(copts.tmpfsPath, &copts.syncPaths, true) case "start": // Check that given TMPFS path does not contain any extra paths which // are not in syncPaths and might not be synced back if ok := checkVolatile(copts.tmpfsPath, &copts.syncPaths); !ok { return 1 } checkAndFix(copts.tmpfsPath, &copts.syncPaths) if err := initSync(copts.tmpfsPath, &copts.syncPaths, copts.syncerBin); err != nil { LOG.Err(err.Error()) return 1 } case "stop": sync(copts.tmpfsPath, &copts.syncPaths, copts.syncerBin) unsync(copts.tmpfsPath, &copts.syncPaths, true) // If not all volatile paths were synced back issue a warning // XXX: checkVolatile actually warns only about volatile paths not in // syncPaths, so if unsync left something from syncPaths unsynced then // checkVolatile would not notice a problem. if ok := checkVolatile(copts.tmpfsPath, &copts.syncPaths); !ok { return 1 } default: LOG.Err("Invalid command provided", err) flag.Usage() return 1 } return 0 }