@@ -22,6 +22,7 @@ import (
22
22
"os"
23
23
osuser "os/user"
24
24
"path"
25
+ "regexp"
25
26
"strconv"
26
27
"strings"
27
28
"time"
@@ -38,20 +39,20 @@ var cl = channel.NewLocalChannel()
38
39
39
40
const DefaultNamespace = "chaosblade"
40
41
41
- func Attach (ctx context.Context , port , javaHome , pid string ) (* spec.Response , string ) {
42
+ func Attach (ctx context.Context , port , javaHome , pid string ) (* spec.Response , string , string ) {
42
43
// refresh
43
- response , username := attach (ctx , pid , port , javaHome )
44
+ response , username , userid := attach (ctx , pid , port , javaHome )
44
45
if ! response .Success {
45
- return response , username
46
+ return response , username , userid
46
47
}
47
48
time .Sleep (5 * time .Second )
48
49
// active
49
50
response = active (ctx , port )
50
51
if ! response .Success {
51
- return response , username
52
+ return response , username , userid
52
53
}
53
54
// check
54
- return check (ctx , port ), username
55
+ return check (ctx , port ), username , userid
55
56
}
56
57
57
58
// curl -s http://localhost:$2/sandbox/default/module/http/chaosblade/status 2>&1
@@ -85,52 +86,72 @@ func active(ctx context.Context, port string) *spec.Response {
85
86
}
86
87
87
88
// attach java agent to application process
88
- func attach (ctx context.Context , pid , port string , javaHome string ) (* spec.Response , string ) {
89
+ func attach (ctx context.Context , pid , port string , javaHome string ) (* spec.Response , string , string ) {
89
90
username , err := getUsername (pid )
91
+ userid := ""
90
92
if err != nil {
91
- log .Errorf (ctx , spec .ProcessGetUsernameFailed .Sprintf (pid , err ))
92
- return spec .ResponseFailWithFlags (spec .ProcessGetUsernameFailed , pid , err ), ""
93
+ userid , err = getUserid (ctx , pid )
94
+ if err != nil {
95
+ log .Errorf (ctx , spec .ProcessGetUsernameFailed .Sprintf (pid , err ))
96
+ return spec .ResponseFailWithFlags (spec .ProcessGetUsernameFailed , pid , err ), "" , ""
97
+ }
93
98
}
94
99
javaBin , javaHome := getJavaBinAndJavaHome (ctx , javaHome , pid , getJavaCommandLine )
95
100
toolsJar := getToolJar (ctx , javaHome )
96
- log .Infof (ctx , "javaBin: %s, javaHome: %s, toolsJar: %s" , javaBin , javaHome , toolsJar )
101
+ log .Infof (ctx , "javaBin: %s, javaHome: %s, toolsJar: %s, username: %s, userid: %s " , javaBin , javaHome , toolsJar , username , userid )
97
102
token , err := getSandboxToken (ctx )
98
103
if err != nil {
99
104
log .Errorf (ctx , spec .SandboxCreateTokenFailed .Sprintf (err ))
100
- return spec .ResponseFailWithFlags (spec .SandboxCreateTokenFailed , err ), username
105
+ return spec .ResponseFailWithFlags (spec .SandboxCreateTokenFailed , err ), username , userid
101
106
}
102
107
javaArgs := getAttachJvmOpts (toolsJar , token , port , pid )
103
108
currUser , err := osuser .Current ()
104
109
if err != nil {
105
- log .Warnf (ctx , "get current user info failed, %v" , err )
110
+ log .Warnf (ctx , "get current user info failed, curr user: %v, %v" , currUser , err )
111
+ if strings .Contains (err .Error (), "unknown userid" ) {
112
+ reg , e := regexp .Compile (`\d+` )
113
+ if e == nil {
114
+ uid := reg .FindString (err .Error ())
115
+ currUser = & osuser.User {
116
+ Uid : uid ,
117
+ }
118
+ }
119
+ }
120
+
106
121
}
122
+
107
123
var command string
108
- if currUser != nil && (currUser .Username == username ) {
124
+ if currUser != nil && (currUser .Username == username || currUser . Uid == userid ) {
109
125
command = fmt .Sprintf ("%s %s" , javaBin , javaArgs )
110
126
} else {
111
127
if currUser != nil {
112
- log .Infof (ctx , "current user name is %s, not equal %s, so use sudo command to execute" ,
113
- currUser .Username , username )
128
+ log .Infof (ctx , "current user name is %s, not equal %s|%s, so use sudo command to execute" ,
129
+ currUser .Username , username , userid )
130
+ }
131
+ if username != "" {
132
+ command = fmt .Sprintf ("sudo -u %s %s %s" , username , javaBin , javaArgs )
133
+ } else if userid != "" {
134
+ command = fmt .Sprintf ("su - #%s -c '%s %s'" , userid , javaBin , javaArgs )
114
135
}
115
- command = fmt . Sprintf ( "sudo -u %s %s %s" , username , javaBin , javaArgs )
136
+
116
137
}
117
138
javaToolOptions := os .Getenv ("JAVA_TOOL_OPTIONS" )
118
139
if javaToolOptions != "" {
119
140
command = fmt .Sprintf ("export JAVA_TOOL_OPTIONS='' && %s" , command )
120
141
}
121
142
response := cl .Run (ctx , "" , command )
122
143
if ! response .Success {
123
- return response , username
144
+ return response , username , userid
124
145
}
125
146
osCmd := fmt .Sprintf ("grep %s" , fmt .Sprintf (`%s %s | grep %s | tail -1 | awk -F ";" '{print $3";"$4}'` ,
126
147
token , getSandboxTokenFile (username ), DefaultNamespace ))
127
148
response = cl .Run (ctx , "" , osCmd )
128
149
// if attach successfully, the sandbox-agent.jar will write token to local file
129
150
if ! response .Success {
130
151
log .Errorf (ctx , spec .OsCmdExecFailed .Sprintf (osCmd , response .Err ))
131
- return spec .ResponseFailWithFlags (spec .OsCmdExecFailed , osCmd , response .Err ), username
152
+ return spec .ResponseFailWithFlags (spec .OsCmdExecFailed , osCmd , response .Err ), username , userid
132
153
}
133
- return response , username
154
+ return response , username , userid
134
155
}
135
156
136
157
func getAttachJvmOpts (toolsJar string , token string , port string , pid string ) string {
@@ -177,6 +198,24 @@ func getUsername(pid string) (string, error) {
177
198
return javaProcess .Username ()
178
199
}
179
200
201
+ func getUserid (ctx context.Context , pid string ) (string , error ) {
202
+ p , err := strconv .Atoi (pid )
203
+ if err != nil {
204
+ return "" , err
205
+ }
206
+ javaProcess , err := process .NewProcess (int32 (p ))
207
+ if err != nil {
208
+ return "" , err
209
+ }
210
+
211
+ userIds , err := javaProcess .Uids ()
212
+ if err == nil && cap (userIds ) > 0 {
213
+ userid := strconv .Itoa (int (userIds [0 ]))
214
+ return userid , err
215
+ }
216
+ return "" , err
217
+ }
218
+
180
219
func getJavaBinAndJavaHome (ctx context.Context , javaHome string , pid string ,
181
220
getJavaCommandLineFunc func (ctx context.Context , pid string ) (commandSlice []string , err error )) (string , string ) {
182
221
javaBin := "java"
0 commit comments