diff --git a/client/control.go b/client/control.go index 07a6d226..f8da9c46 100644 --- a/client/control.go +++ b/client/control.go @@ -19,6 +19,7 @@ import ( "crypto/tls" "io" "net" + "os" "runtime/debug" "strconv" "sync" @@ -87,6 +88,8 @@ type Control struct { // sets authentication based on selected method authSetter auth.Setter + + timeOutExit int64 } func NewControl(ctx context.Context, runID string, conn net.Conn, session *fmux.Session, @@ -114,6 +117,7 @@ func NewControl(ctx context.Context, runID string, conn net.Conn, session *fmux. xl: xlog.FromContextSafe(ctx), ctx: ctx, authSetter: authSetter, + timeOutExit: clientCfg.TimeOutExit, } ctl.pm = proxy.NewManager(ctl.ctx, ctl.sendCh, clientCfg, serverUDPPort) @@ -341,6 +345,13 @@ func (ctl *Control) msgHandler() { } ctl.sendCh <- pingMsg case <-hbCheckCh: + if ctl.clientCfg.TimeOutExit > 0 { + ctl.timeOutExit-- + if ctl.timeOutExit <= 0 { + xl.Debug("exit --------------------", ctl.timeOutExit) + os.Exit(0) + } + } if time.Since(ctl.lastPong) > time.Duration(ctl.clientCfg.HeartbeatTimeout)*time.Second { xl.Warn("heartbeat timeout") // let reader() stop @@ -354,8 +365,10 @@ func (ctl *Control) msgHandler() { switch m := rawMsg.(type) { case *msg.ReqWorkConn: + ctl.timeOutExit = ctl.clientCfg.TimeOutExit go ctl.HandleReqWorkConn(m) case *msg.NewProxyResp: + ctl.timeOutExit = ctl.clientCfg.TimeOutExit ctl.HandleNewProxyResp(m) case *msg.Pong: if m.Error != "" { diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go index d03cdd12..f54afdba 100644 --- a/cmd/frpc/sub/root.go +++ b/cmd/frpc/sub/root.go @@ -71,7 +71,8 @@ var ( bindAddr string bindPort int - tlsEnable bool + tlsEnable bool + timeOutExit int kcpDoneCh chan struct{} ) @@ -93,6 +94,7 @@ func RegisterCommonFlags(cmd *cobra.Command) { cmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") cmd.PersistentFlags().BoolVarP(&disableLogColor, "disable_log_color", "", false, "disable log color in console") cmd.PersistentFlags().BoolVarP(&tlsEnable, "tls_enable", "", false, "enable frpc tls") + cmd.PersistentFlags().IntVarP(&timeOutExit, "timeout_exit", "", -1, "time out exit frpc") } var rootCmd = &cobra.Command{ @@ -150,7 +152,7 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) { cfg.LogFile = logFile cfg.LogMaxDays = int64(logMaxDays) cfg.DisableLogColor = disableLogColor - + cfg.TimeOutExit = int64(timeOutExit) // Only token authentication is supported in cmd mode cfg.ClientConfig = auth.GetDefaultClientConf() cfg.Token = token diff --git a/pkg/config/client.go b/pkg/config/client.go index f2d1a07d..1674c912 100644 --- a/pkg/config/client.go +++ b/pkg/config/client.go @@ -145,6 +145,8 @@ type ClientCommonConf struct { UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"` // Include other config files for proxies. IncludeConfigFiles []string `ini:"includes" json:"includes"` + // There is no data interaction between frpc and frps, timeout exit + TimeOutExit int64 `ini:"timeout_exit" json:"timeout_exit"` } // GetDefaultClientConf returns a client configuration with default values.