@@ -22,6 +22,7 @@ import (
2222 "os"
2323 osuser "os/user"
2424 "path"
25+ "regexp"
2526 "strconv"
2627 "strings"
2728 "time"
@@ -38,20 +39,20 @@ var cl = channel.NewLocalChannel()
3839
3940const DefaultNamespace = "chaosblade"
4041
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 ) {
4243 // refresh
43- response , username := attach (ctx , pid , port , javaHome )
44+ response , username , userid := attach (ctx , pid , port , javaHome )
4445 if ! response .Success {
45- return response , username
46+ return response , username , userid
4647 }
4748 time .Sleep (5 * time .Second )
4849 // active
4950 response = active (ctx , port )
5051 if ! response .Success {
51- return response , username
52+ return response , username , userid
5253 }
5354 // check
54- return check (ctx , port ), username
55+ return check (ctx , port ), username , userid
5556}
5657
5758// 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 {
8586}
8687
8788// 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 ) {
8990 username , err := getUsername (pid )
91+ userid := ""
9092 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+ }
9398 }
9499 javaBin , javaHome := getJavaBinAndJavaHome (ctx , javaHome , pid , getJavaCommandLine )
95100 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 )
97102 token , err := getSandboxToken (ctx )
98103 if err != nil {
99104 log .Errorf (ctx , spec .SandboxCreateTokenFailed .Sprintf (err ))
100- return spec .ResponseFailWithFlags (spec .SandboxCreateTokenFailed , err ), username
105+ return spec .ResponseFailWithFlags (spec .SandboxCreateTokenFailed , err ), username , userid
101106 }
102107 javaArgs := getAttachJvmOpts (toolsJar , token , port , pid )
103108 currUser , err := osuser .Current ()
104109 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+
106121 }
122+
107123 var command string
108- if currUser != nil && (currUser .Username == username ) {
124+ if currUser != nil && (currUser .Username == username || currUser . Uid == userid ) {
109125 command = fmt .Sprintf ("%s %s" , javaBin , javaArgs )
110126 } else {
111127 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 )
114135 }
115- command = fmt . Sprintf ( "sudo -u %s %s %s" , username , javaBin , javaArgs )
136+
116137 }
117138 javaToolOptions := os .Getenv ("JAVA_TOOL_OPTIONS" )
118139 if javaToolOptions != "" {
119140 command = fmt .Sprintf ("export JAVA_TOOL_OPTIONS='' && %s" , command )
120141 }
121142 response := cl .Run (ctx , "" , command )
122143 if ! response .Success {
123- return response , username
144+ return response , username , userid
124145 }
125146 osCmd := fmt .Sprintf ("grep %s" , fmt .Sprintf (`%s %s | grep %s | tail -1 | awk -F ";" '{print $3";"$4}'` ,
126147 token , getSandboxTokenFile (username ), DefaultNamespace ))
127148 response = cl .Run (ctx , "" , osCmd )
128149 // if attach successfully, the sandbox-agent.jar will write token to local file
129150 if ! response .Success {
130151 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
132153 }
133- return response , username
154+ return response , username , userid
134155}
135156
136157func getAttachJvmOpts (toolsJar string , token string , port string , pid string ) string {
@@ -177,6 +198,24 @@ func getUsername(pid string) (string, error) {
177198 return javaProcess .Username ()
178199}
179200
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+
180219func getJavaBinAndJavaHome (ctx context.Context , javaHome string , pid string ,
181220 getJavaCommandLineFunc func (ctx context.Context , pid string ) (commandSlice []string , err error )) (string , string ) {
182221 javaBin := "java"
0 commit comments