@ -36,8 +36,8 @@ var debugCmd = &ffcli.Command{
fs . BoolVar ( & debugArgs . netMap , "netmap" , true , "whether to include netmap in --ipn mode" )
fs . BoolVar ( & debugArgs . localCreds , "local-creds" , false , "print how to connect to local tailscaled" )
fs . StringVar ( & debugArgs . file , "file" , "" , "get, delete:NAME, or NAME" )
fs . StringVar ( & debugArgs . cpuFile , "cpu-profile" , "" , "if non-empty, grab a CPU profile for --profile-sec seconds and write it to this file ")
fs . StringVar ( & debugArgs . memFile , "mem-profile" , "" , "if non-empty, grab a memory profile and write it to this file ")
fs . StringVar ( & debugArgs . cpuFile , "cpu-profile" , "" , "if non-empty, grab a CPU profile for --profile-sec seconds and write it to this file ; - for stdout ")
fs . StringVar ( & debugArgs . memFile , "mem-profile" , "" , "if non-empty, grab a memory profile and write it to this file ; - for stdout ")
fs . IntVar ( & debugArgs . cpuSec , "profile-seconds" , 15 , "number of seconds to run a CPU profile for, when --cpu-profile is non-empty" )
return fs
} ) ( ) ,
@ -57,6 +57,24 @@ var debugArgs struct {
memFile string
}
func writeProfile ( dst string , v [ ] byte ) error {
if dst == "-" {
_ , err := os . Stdout . Write ( v )
return err
}
return os . WriteFile ( dst , v , 0600 )
}
func outName ( dst string ) string {
if dst == "-" {
return "stdout"
}
if runtime . GOOS == "darwin" {
return fmt . Sprintf ( "%s (warning: sandboxed macOS binaries write to Library/Containers; use - to write to stdout and redirect to file instead)" , dst )
}
return dst
}
func runDebug ( ctx context . Context , args [ ] string ) error {
if len ( args ) > 0 {
return errors . New ( "unknown arguments" )
@ -79,10 +97,10 @@ func runDebug(ctx context.Context, args []string) error {
if v , err := tailscale . Profile ( ctx , "profile" , debugArgs . cpuSec ) ; err != nil {
return err
} else {
if err := os . WriteFile ( out , v , 0600 ) ; err != nil {
if err := writeProfile ( out , v ) ; err != nil {
return err
}
log . Printf ( "CPU profile written to %s" , out )
log . Printf ( "CPU profile written to %s" , outName ( out ) )
}
}
if out := debugArgs . memFile ; out != "" {
@ -90,10 +108,10 @@ func runDebug(ctx context.Context, args []string) error {
if v , err := tailscale . Profile ( ctx , "heap" , 0 ) ; err != nil {
return err
} else {
if err := os . WriteFile ( out , v , 0600 ) ; err != nil {
if err := writeProfile ( out , v ) ; err != nil {
return err
}
log . Printf ( "Memory profile written to %s" , out )
log . Printf ( "Memory profile written to %s" , outName ( out ) )
}
}
if debugArgs . prefs {