// LaunchCollector launches a new syslog server and starts writing log lines to // files and rotates them func (s *SyslogCollector) LaunchCollector(ctx *LogCollectorContext) (*SyslogCollectorState, error) { addr, err := s.getFreePort(ctx.PortLowerBound, ctx.PortUpperBound) if err != nil { return nil, err } s.logger.Printf("[DEBUG] sylog-server: launching syslog server on addr: %v", addr) s.ctx = ctx // configuring the task dir if err := s.configureTaskDir(); err != nil { return nil, err } channel := make(syslog.LogPartsChannel) handler := syslog.NewChannelHandler(channel) s.server = syslog.NewServer() s.server.SetFormat(&CustomParser{logger: s.logger}) s.server.SetHandler(handler) s.server.ListenTCP(addr.String()) if err := s.server.Boot(); err != nil { return nil, err } logFileSize := int64(ctx.LogConfig.MaxFileSizeMB * 1024 * 1024) ro, wo := io.Pipe() lro, err := logrotator.NewLogRotator(filepath.Join(s.taskDir, allocdir.TaskLocal), fmt.Sprintf("%v.stdout", ctx.TaskName), ctx.LogConfig.MaxFiles, logFileSize, s.logger) if err != nil { return nil, err } s.lro = lro go lro.Start(ro) re, we := io.Pipe() lre, err := logrotator.NewLogRotator(filepath.Join(s.taskDir, allocdir.TaskLocal), fmt.Sprintf("%v.stderr", ctx.TaskName), ctx.LogConfig.MaxFiles, logFileSize, s.logger) if err != nil { return nil, err } s.lre = lre go lre.Start(re) go func(channel syslog.LogPartsChannel) { for logParts := range channel { // If the severity of the log line is err then we write to stderr // otherwise all messages go to stdout s := logParts["severity"].(Priority) if s.Severity == s1.LOG_ERR { we.Write(logParts["content"].([]byte)) } else { wo.Write(logParts["content"].([]byte)) } wo.Write([]byte("\n")) } }(channel) go s.server.Wait() return &SyslogCollectorState{Addr: addr.String()}, nil }
// LaunchCmd launches a process and returns it's state. It also configures an // applies isolation on certain platforms. func (e *UniversalExecutor) LaunchCmd(command *ExecCommand, ctx *ExecutorContext) (*ProcessState, error) { e.logger.Printf("[DEBUG] executor: launching command %v %v", command.Cmd, strings.Join(command.Args, "")) e.ctx = ctx // configuring the task dir if err := e.configureTaskDir(); err != nil { return nil, err } // configuring the chroot, cgroup and enters the plugin process in the // chroot if err := e.configureIsolation(); err != nil { return nil, err } // setting the user of the process if e.ctx.UnprivilegedUser { if err := e.runAs("nobody"); err != nil { return nil, err } } logFileSize := int64(ctx.LogConfig.MaxFileSizeMB * 1024 * 1024) stdor, stdow := io.Pipe() lro, err := logrotator.NewLogRotator(filepath.Join(e.taskDir, allocdir.TaskLocal), fmt.Sprintf("%v.stdout", ctx.TaskName), ctx.LogConfig.MaxFiles, logFileSize, e.logger) if err != nil { return nil, fmt.Errorf("error creating log rotator for stdout of task %v", err) } e.cmd.Stdout = stdow e.lro = lro go lro.Start(stdor) stder, stdew := io.Pipe() lre, err := logrotator.NewLogRotator(filepath.Join(e.taskDir, allocdir.TaskLocal), fmt.Sprintf("%v.stderr", ctx.TaskName), ctx.LogConfig.MaxFiles, logFileSize, e.logger) if err != nil { return nil, fmt.Errorf("error creating log rotator for stderr of task %v", err) } e.cmd.Stderr = stdew e.lre = lre go lre.Start(stder) // setting the env, path and args for the command e.ctx.TaskEnv.Build() e.cmd.Env = ctx.TaskEnv.EnvList() e.cmd.Path = ctx.TaskEnv.ReplaceEnv(command.Cmd) e.cmd.Args = append([]string{e.cmd.Path}, ctx.TaskEnv.ParseAndReplace(command.Args)...) if filepath.Base(command.Cmd) == command.Cmd { if lp, err := exec.LookPath(command.Cmd); err != nil { } else { e.cmd.Path = lp } } // starting the process if err := e.cmd.Start(); err != nil { return nil, fmt.Errorf("error starting command: %v", err) } go e.wait() ic := &IsolationConfig{Cgroup: e.groups} return &ProcessState{Pid: e.cmd.Process.Pid, ExitCode: -1, IsolationConfig: ic, Time: time.Now()}, nil }