15
15
package sub
16
16
17
17
import (
18
- "context"
19
18
"fmt"
19
+ "io/fs"
20
20
"net"
21
21
"os"
22
22
"os/signal"
23
+ "path/filepath"
23
24
"strconv"
24
- "strings "
25
+ "sync "
25
26
"syscall"
26
27
"time"
27
28
@@ -41,6 +42,7 @@ const (
41
42
42
43
var (
43
44
cfgFile string
45
+ cfgDir string
44
46
showVersion bool
45
47
46
48
serverAddr string
@@ -72,15 +74,12 @@ var (
72
74
bindPort int
73
75
74
76
tlsEnable bool
75
-
76
- kcpDoneCh chan struct {}
77
77
)
78
78
79
79
func init () {
80
80
rootCmd .PersistentFlags ().StringVarP (& cfgFile , "config" , "c" , "./frpc.ini" , "config file of frpc" )
81
+ rootCmd .PersistentFlags ().StringVarP (& cfgDir , "config_dir" , "" , "" , "config directory, run one frpc service for each file in config directory" )
81
82
rootCmd .PersistentFlags ().BoolVarP (& showVersion , "version" , "v" , false , "version of frpc" )
82
-
83
- kcpDoneCh = make (chan struct {})
84
83
}
85
84
86
85
func RegisterCommonFlags (cmd * cobra.Command ) {
@@ -104,6 +103,32 @@ var rootCmd = &cobra.Command{
104
103
return nil
105
104
}
106
105
106
+ // If cfgDir is not empty, run multiple frpc service for each config file in cfgDir.
107
+ // Note that it's only designed for testing. It's not guaranteed to be stable.
108
+ if cfgDir != "" {
109
+ var wg sync.WaitGroup
110
+ filepath .WalkDir (cfgDir , func (path string , d fs.DirEntry , err error ) error {
111
+ if err != nil {
112
+ return nil
113
+ }
114
+ if d .IsDir () {
115
+ return nil
116
+ }
117
+ wg .Add (1 )
118
+ time .Sleep (time .Millisecond )
119
+ go func () {
120
+ defer wg .Done ()
121
+ err := runClient (path )
122
+ if err != nil {
123
+ fmt .Printf ("frpc service error for config file [%s]\n " , path )
124
+ }
125
+ }()
126
+ return nil
127
+ })
128
+ wg .Wait ()
129
+ return nil
130
+ }
131
+
107
132
// Do not show command usage here.
108
133
err := runClient (cfgFile )
109
134
if err != nil {
@@ -120,12 +145,12 @@ func Execute() {
120
145
}
121
146
}
122
147
123
- func handleSignal (svr * client.Service ) {
124
- ch := make (chan os.Signal )
148
+ func handleSignal (svr * client.Service , doneCh chan struct {} ) {
149
+ ch := make (chan os.Signal , 1 )
125
150
signal .Notify (ch , syscall .SIGINT , syscall .SIGTERM )
126
151
<- ch
127
152
svr .GracefulClose (500 * time .Millisecond )
128
- close (kcpDoneCh )
153
+ close (doneCh )
129
154
}
130
155
131
156
func parseClientCommonCfgFromCmd () (cfg config.ClientCommonConf , err error ) {
@@ -182,28 +207,20 @@ func startService(
182
207
log .InitLog (cfg .LogWay , cfg .LogFile , cfg .LogLevel ,
183
208
cfg .LogMaxDays , cfg .DisableLogColor )
184
209
185
- if cfg .DNSServer != "" {
186
- s := cfg .DNSServer
187
- if ! strings .Contains (s , ":" ) {
188
- s += ":53"
189
- }
190
- // Change default dns server for frpc
191
- net .DefaultResolver = & net.Resolver {
192
- PreferGo : true ,
193
- Dial : func (ctx context.Context , network , address string ) (net.Conn , error ) {
194
- return net .Dial ("udp" , s )
195
- },
196
- }
210
+ if cfgFile != "" {
211
+ log .Trace ("start frpc service for config file [%s]" , cfgFile )
212
+ defer log .Trace ("frpc service for config file [%s] stopped" , cfgFile )
197
213
}
198
214
svr , errRet := client .NewService (cfg , pxyCfgs , visitorCfgs , cfgFile )
199
215
if errRet != nil {
200
216
err = errRet
201
217
return
202
218
}
203
219
220
+ kcpDoneCh := make (chan struct {})
204
221
// Capture the exit signal if we use kcp.
205
222
if cfg .Protocol == "kcp" {
206
- go handleSignal (svr )
223
+ go handleSignal (svr , kcpDoneCh )
207
224
}
208
225
209
226
err = svr .Run ()
0 commit comments