Skip to content

Commit 5e9228e

Browse files
authored
Merge pull request #1049 from chaosblade-io/1.7.4-fix-jvm-cannot-exec-by-username
Enhancement : attach appliction but cannt get userName
2 parents 3ed768a + ffa6d94 commit 5e9228e

File tree

7 files changed

+119
-78
lines changed

7 files changed

+119
-78
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.PHONY: build clean
22

3-
export BLADE_VERSION=1.7.3
3+
export BLADE_VERSION=1.7.4
44

55
ALLOWGITVERSION=1.8.5
66
GITVERSION:=$(shell git --version | grep ^git | sed 's/^.* //g')

build/spec/spec.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
"github.com/chaosblade-io/chaosblade/cli/cmd"
3030
)
3131

32-
var version = "1.7.3"
32+
var version = "1.7.4"
3333

3434
func main() {
3535

cli/cmd/prepare_jvm.go

+20-19
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ import (
2020
"context"
2121
"encoding/json"
2222
"fmt"
23-
"github.com/chaosblade-io/chaosblade-spec-go/log"
2423
"path"
2524
"strconv"
2625
"strings"
2726
"time"
2827

28+
"github.com/chaosblade-io/chaosblade-spec-go/log"
29+
2930
"github.com/chaosblade-io/chaosblade-spec-go/channel"
3031
"github.com/chaosblade-io/chaosblade-spec-go/spec"
3132
"github.com/chaosblade-io/chaosblade-spec-go/util"
@@ -145,13 +146,13 @@ func (pc *PrepareJvmCommand) reportAttachedResult(ctx context.Context, response
145146

146147
// attachAgent
147148
func (pc *PrepareJvmCommand) attachAgent(ctx context.Context) *spec.Response {
148-
response, username := jvm.Attach(ctx, strconv.Itoa(pc.port), pc.javaHome, pc.processId)
149-
if !response.Success && username != "" && strings.Contains(response.Err, "connection refused") {
149+
response, username, userid := jvm.Attach(ctx, strconv.Itoa(pc.port), pc.javaHome, pc.processId)
150+
if !response.Success && (username != "" || userid != "") && strings.Contains(response.Err, "connection refused") {
150151
// if attach failed, search port from ~/.sandbox.token
151152
port, err := jvm.CheckPortFromSandboxToken(ctx, username)
152153
if err == nil {
153154
log.Infof(ctx, "use %s port to retry", port)
154-
response, username = jvm.Attach(ctx, port, pc.javaHome, pc.processId)
155+
response, username, userid = jvm.Attach(ctx, port, pc.javaHome, pc.processId)
155156
if response.Success {
156157
// update port
157158
err := updatePreparationPort(pc.uid, port)
@@ -228,21 +229,21 @@ func (pc *PrepareJvmCommand) invokeAttaching(ctx context.Context, port string, u
228229
}
229230

230231
/*
231-
{
232-
"data":{ #PreparestatusBean
233-
"createTime":"",
234-
"error":"",
235-
"pid":"",
236-
"port":"",
237-
"process":"sss",
238-
"running":false,
239-
"status":"",
240-
"type":"",
241-
"uid":"",
242-
"updateTime":""
243-
},
244-
"type":"JAVA_AGENT_PREPARE"
245-
}
232+
{
233+
"data":{ #PreparestatusBean
234+
"createTime":"",
235+
"error":"",
236+
"pid":"",
237+
"port":"",
238+
"process":"sss",
239+
"running":false,
240+
"status":"",
241+
"type":"",
242+
"uid":"",
243+
"updateTime":""
244+
},
245+
"type":"JAVA_AGENT_PREPARE"
246+
}
246247
*/
247248
func createPostBody(ctx context.Context) ([]byte, error) {
248249
preparationRecord, err := GetDS().QueryPreparationByUid(uid)

exec/jvm/executor.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ import (
2020
"context"
2121
"encoding/json"
2222
"fmt"
23-
"github.com/chaosblade-io/chaosblade-spec-go/log"
2423
"strconv"
2524
"strings"
2625
"time"
2726

27+
"github.com/chaosblade-io/chaosblade-spec-go/log"
28+
2829
"github.com/chaosblade-io/chaosblade-spec-go/channel"
2930
"github.com/chaosblade-io/chaosblade-spec-go/spec"
3031
"github.com/chaosblade-io/chaosblade-spec-go/util"
@@ -378,15 +379,15 @@ func Prepare(ctx context.Context, processName, processId, javaHome string) (resp
378379
return spec.ResponseFailWithFlags(spec.DatabaseError, "insert", err), port
379380
}
380381
}
381-
var username string
382+
var username, userid string
382383
port = record.Port
383-
response, username = Attach(ctx, port, javaHome, processId)
384-
if !response.Success && username != "" && strings.Contains(response.Err, "connection refused") {
384+
response, username, userid = Attach(ctx, port, javaHome, processId)
385+
if !response.Success && (username != "" || userid != "") && strings.Contains(response.Err, "connection refused") {
385386
// if attach failed, search port from ~/.sandbox.token
386387
port, err = CheckPortFromSandboxToken(ctx, username)
387388
if err == nil {
388389
log.Infof(ctx, "use %s port to retry", port)
389-
response, username = Attach(ctx, port, "", processId)
390+
response, username, userid = Attach(ctx, port, "", processId)
390391
if response.Success {
391392
// update port
392393
err := db.UpdatePreparationPortByUid(record.Uid, port)

exec/jvm/sandbox.go

+57-18
Original file line numberDiff line numberDiff line change
@@ -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

3940
const 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

136157
func 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+
180219
func 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"

go.mod

+11-11
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ module github.com/chaosblade-io/chaosblade
33
go 1.20
44

55
require (
6-
github.com/chaosblade-io/chaosblade-exec-cloud v1.7.3
7-
github.com/chaosblade-io/chaosblade-exec-cri v1.7.3
8-
github.com/chaosblade-io/chaosblade-exec-middleware v1.7.3
9-
github.com/chaosblade-io/chaosblade-exec-os v1.7.3
10-
github.com/chaosblade-io/chaosblade-operator v1.7.3
11-
github.com/chaosblade-io/chaosblade-spec-go v1.7.3
6+
github.com/chaosblade-io/chaosblade-exec-cloud v1.7.4
7+
github.com/chaosblade-io/chaosblade-exec-cri v1.7.4
8+
github.com/chaosblade-io/chaosblade-exec-middleware v1.7.4
9+
github.com/chaosblade-io/chaosblade-exec-os v1.7.4
10+
github.com/chaosblade-io/chaosblade-operator v1.7.4
11+
github.com/chaosblade-io/chaosblade-spec-go v1.7.4
1212
github.com/mattn/go-sqlite3 v1.10.1-0.20190217174029-ad30583d8387
1313
github.com/olekukonko/tablewriter v0.0.5-0.20201029120751-42e21c7531a3
14-
github.com/shirou/gopsutil v3.21.8-0.20210816101416-f86a04298073+incompatible
14+
github.com/shirou/gopsutil v3.21.11+incompatible
1515
github.com/spf13/cobra v1.0.0
1616
github.com/spf13/pflag v1.0.5
1717
golang.org/x/crypto v0.1.0
@@ -25,7 +25,6 @@ require (
2525
github.com/Microsoft/hcsshim v0.8.21 // indirect
2626
github.com/PuerkitoBio/purell v1.1.1 // indirect
2727
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
28-
github.com/StackExchange/wmi v1.2.1 // indirect
2928
github.com/beorn7/perks v1.0.1 // indirect
3029
github.com/bits-and-blooms/bitset v1.2.0 // indirect
3130
github.com/cespare/xxhash/v2 v2.1.2 // indirect
@@ -46,7 +45,7 @@ require (
4645
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
4746
github.com/evanphx/json-patch v4.9.0+incompatible // indirect
4847
github.com/go-logr/logr v0.2.1 // indirect
49-
github.com/go-ole/go-ole v1.2.5 // indirect
48+
github.com/go-ole/go-ole v1.2.6 // indirect
5049
github.com/go-openapi/jsonpointer v0.19.3 // indirect
5150
github.com/go-openapi/jsonreference v0.19.3 // indirect
5251
github.com/go-openapi/spec v0.19.4 // indirect
@@ -85,8 +84,9 @@ require (
8584
github.com/prometheus/common v0.10.0 // indirect
8685
github.com/prometheus/procfs v0.6.0 // indirect
8786
github.com/sirupsen/logrus v1.8.1 // indirect
88-
github.com/tklauser/go-sysconf v0.3.7 // indirect
89-
github.com/tklauser/numcpus v0.2.3 // indirect
87+
github.com/tklauser/go-sysconf v0.3.9 // indirect
88+
github.com/tklauser/numcpus v0.3.0 // indirect
89+
github.com/yusufpapurcu/wmi v1.2.4 // indirect
9090
go.opencensus.io v0.22.3 // indirect
9191
go.uber.org/automaxprocs v1.3.0 // indirect
9292
golang.org/x/net v0.1.0 // indirect

0 commit comments

Comments
 (0)