WIP: rebase fork onto upstream/main (v1.103.0) #15
@@ -323,6 +323,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
tailscale.com/feature/runtimemetrics from tailscale.com/feature/condregister
|
||||
L tailscale.com/feature/sdnotify from tailscale.com/feature/condregister
|
||||
LD tailscale.com/feature/ssh from tailscale.com/cmd/tailscaled
|
||||
L tailscale.com/feature/syslog from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/syspolicy from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/taildrop from tailscale.com/feature/condregister
|
||||
tailscale.com/feature/tailnetlock from tailscale.com/feature/condregister
|
||||
@@ -745,7 +746,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
||||
iter from maps+
|
||||
log from expvar+
|
||||
log/internal from log
|
||||
LD log/syslog from tailscale.com/ssh/tailssh
|
||||
LD log/syslog from tailscale.com/ssh/tailssh+
|
||||
maps from tailscale.com/clientupdate+
|
||||
math from archive/tar+
|
||||
math/big from crypto/dsa+
|
||||
|
||||
@@ -33,6 +33,21 @@ func TestOmitSSH(t *testing.T) {
|
||||
}.Check(t)
|
||||
}
|
||||
|
||||
func TestOmitSyslog(t *testing.T) {
|
||||
const msg = "unexpected syslog usage with ts_omit_syslog"
|
||||
deptest.DepChecker{
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
// Tailscale SSH's incubator also uses log/syslog, so omit
|
||||
// SSH too to lock down the standard library package.
|
||||
Tags: "ts_omit_syslog,ts_omit_ssh,ts_include_cli",
|
||||
BadDeps: map[string]string{
|
||||
"log/syslog": msg,
|
||||
"tailscale.com/feature/syslog": msg,
|
||||
},
|
||||
}.Check(t)
|
||||
}
|
||||
|
||||
func TestOmitSyspolicy(t *testing.T) {
|
||||
const msg = "unexpected syspolicy usage with ts_omit_syspolicy"
|
||||
deptest.DepChecker{
|
||||
|
||||
@@ -233,6 +233,9 @@ store state on filesystem.`)
|
||||
if f, ok := hookRegisterOutboundProxyFlags.GetOk(); ok {
|
||||
f()
|
||||
}
|
||||
if f, ok := feature.HookRegisterLogSinkFlags.GetOk(); ok {
|
||||
f()
|
||||
}
|
||||
|
||||
if runtime.GOOS == "plan9" && os.Getenv("_NETSHELL_CHILD_") != "" {
|
||||
os.Args = []string{"tailscaled", "be-child", "plan9-netshell"}
|
||||
@@ -261,6 +264,10 @@ store state on filesystem.`)
|
||||
}
|
||||
}
|
||||
|
||||
if f, ok := feature.HookLogSink.GetOk(); ok {
|
||||
f() // redirects the default logger (e.g. to syslog) if requested by flags
|
||||
}
|
||||
|
||||
if fd, ok := envknob.LookupInt("TS_PARENT_DEATH_FD"); ok && fd > 2 {
|
||||
go dieOnPipeReadErrorOfFD(fd)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Code generated by gen.go; DO NOT EDIT.
|
||||
|
||||
//go:build ts_omit_syslog
|
||||
|
||||
package buildfeatures
|
||||
|
||||
// HasSyslog is whether the binary was built with support for modular feature "tailscaled --syslog flag support to send logs to the system syslog daemon".
|
||||
// Specifically, it's whether the binary was NOT built with the "ts_omit_syslog" build tag.
|
||||
// It's a const so it can be used for dead code elimination.
|
||||
const HasSyslog = false
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Code generated by gen.go; DO NOT EDIT.
|
||||
|
||||
//go:build !ts_omit_syslog
|
||||
|
||||
package buildfeatures
|
||||
|
||||
// HasSyslog is whether the binary was built with support for modular feature "tailscaled --syslog flag support to send logs to the system syslog daemon".
|
||||
// Specifically, it's whether the binary was NOT built with the "ts_omit_syslog" build tag.
|
||||
// It's a const so it can be used for dead code elimination.
|
||||
const HasSyslog = true
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build (linux || freebsd || openbsd) && !ts_omit_syslog
|
||||
|
||||
package condregister
|
||||
|
||||
import _ "tailscale.com/feature/syslog"
|
||||
@@ -267,6 +267,10 @@ var Features = map[FeatureTag]FeatureMeta{
|
||||
Sym: "Synology",
|
||||
Desc: "Synology NAS integration (applies to Linux builds only)",
|
||||
},
|
||||
"syslog": {
|
||||
Sym: "Syslog",
|
||||
Desc: "tailscaled --syslog flag support to send logs to the system syslog daemon",
|
||||
},
|
||||
"syspolicy": {Sym: "SystemPolicy", Desc: "System policy configuration (MDM) support"},
|
||||
"systray": {
|
||||
Sym: "SysTray",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package feature
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -13,6 +14,21 @@ import (
|
||||
"tailscale.com/types/persist"
|
||||
)
|
||||
|
||||
// HookRegisterLogSinkFlags is a hook for the syslog feature to register
|
||||
// its flags (such as tailscaled's --syslog) with the process's default
|
||||
// flag set. If set, tailscaled calls it before flag parsing.
|
||||
var HookRegisterLogSinkFlags Hook[func()]
|
||||
|
||||
// HookLogSink is a hook for the syslog feature to redirect the process's
|
||||
// logs to an alternate sink. If set, tailscaled calls it once early in
|
||||
// main, after flag parsing; on that first call, if the user requested an
|
||||
// alternate sink, it points the standard library's default logger at that
|
||||
// sink. It returns the sink, or nil if logs are not being redirected.
|
||||
// Later callers (such as logpolicy, which otherwise writes its console
|
||||
// copy of logs to stderr) use the returned writer to send their logs to
|
||||
// the same place.
|
||||
var HookLogSink Hook[func() io.Writer]
|
||||
|
||||
// HookCanAutoUpdate is a hook for the clientupdate package
|
||||
// to conditionally initialize.
|
||||
var HookCanAutoUpdate Hook[func() bool]
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build unix
|
||||
|
||||
// Package syslog provides the tailscaled --syslog flag, which sends the
|
||||
// daemon's logs to the system syslog daemon instead of stderr.
|
||||
package syslog
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"log/syslog"
|
||||
"sync"
|
||||
|
||||
"tailscale.com/feature"
|
||||
)
|
||||
|
||||
func init() {
|
||||
feature.Register("syslog")
|
||||
feature.HookRegisterLogSinkFlags.Set(registerFlags)
|
||||
feature.HookLogSink.Set(logSink)
|
||||
}
|
||||
|
||||
var useSyslog bool
|
||||
|
||||
func registerFlags() {
|
||||
flag.BoolVar(&useSyslog, "syslog", false, "log to the system syslog daemon instead of stderr")
|
||||
}
|
||||
|
||||
// logSink returns the writer to which logs should be sent, pointing the
|
||||
// standard library's default logger at it on first call. It returns nil if
|
||||
// syslog logging was not requested or the syslog daemon is unreachable.
|
||||
var logSink = sync.OnceValue(func() io.Writer {
|
||||
if !useSyslog {
|
||||
return nil
|
||||
}
|
||||
w, err := syslog.New(syslog.LOG_DAEMON|syslog.LOG_INFO, "tailscaled")
|
||||
if err != nil {
|
||||
log.Printf("syslog: connecting to syslog daemon failed; continuing to log to stderr: %v", err)
|
||||
return nil
|
||||
}
|
||||
log.SetFlags(0) // syslog records its own timestamps
|
||||
log.SetOutput(w)
|
||||
return w
|
||||
})
|
||||
+12
-1
@@ -546,7 +546,18 @@ func (opts Options) init(disableLogging bool) (*logtail.Config, *Policy) {
|
||||
// anyway, no need to add one.
|
||||
lflags = 0
|
||||
}
|
||||
console := log.New(stderrWriter{}, "", lflags)
|
||||
var conWriter io.Writer = stderrWriter{}
|
||||
if buildfeatures.HasSyslog {
|
||||
if f, ok := feature.HookLogSink.GetOk(); ok {
|
||||
if w := f(); w != nil {
|
||||
// Logs are being redirected elsewhere (e.g. to syslog,
|
||||
// which records its own timestamps).
|
||||
conWriter = w
|
||||
lflags = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
console := log.New(conWriter, "", lflags)
|
||||
|
||||
var earlyErrBuf bytes.Buffer
|
||||
earlyLogf := func(format string, a ...any) {
|
||||
|
||||
Reference in New Issue
Block a user