英文:
Permission denied while reading /proc/pid/smaps file (golang)
问题
使用os/exec
包,我想在*nix操作系统上以另一个用户而不是root用户身份运行外部命令(主进程在root用户下运行)。
外部命令由go应用程序运行。但是我的应用程序无法读取/proc/pid/smaps
文件,出现以下错误:
panic: open /proc/2962/smaps: permission denied
goroutine 6 [running]:
main.memwatch(0xc000094000, 0xc00007a0c0)
/src/main.go:41 +0x298
created by main.main
/src/main.go:25 +0x18f
exit status 2
以下是我的代码:
// main.go
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
"time"
)
func main() {
cmd := exec.Command("sleep", "3")
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Credential: &syscall.Credential{Uid: 65534, Gid: 65534}, // 由于安全原因,外部命令期望以`nobody`而不是`root`用户身份运行
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Start()
done := make(chan struct{})
go memwatch(cmd, done)
if err != nil {
panic(err)
}
cmd.Wait()
close(done)
}
func memwatch(cmd *exec.Cmd, done <-chan struct{}) {
// 重用读取器,这样我们就不必一直关闭和重新打开它
smaps, err := os.Open(fmt.Sprintf("/proc/%d/smaps", cmd.Process.Pid))
if err != nil {
panic(err)
}
defer smaps.Close()
for {
select {
case <-done:
return
default:
fmt.Println("running")
time.Sleep(10 * time.Millisecond)
}
}
}
我很累了。有人可以帮忙吗?谢谢。
英文:
Using the os/exec
package, I want to run an external command on a *nix OS with another user instead of root. (The main process runs under root user).
The external command runs by go app. But my app can not read /proc/pid/smaps
file, following error:
panic: open /proc/2962/smaps: permission denied
goroutine 6 [running]:
main.memwatch(0xc000094000, 0xc00007a0c0)
/src/main.go:41 +0x298
created by main.main
/src/main.go:25 +0x18f
exit status 2
Here is my code:
// main.go
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
"time"
)
func main() {
cmd := exec.Command("sleep", "3")
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Credential: &syscall.Credential{Uid: 65534, Gid: 65534}, // External command expect run with `nobody` instead of `root` for security reason
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Start()
done := make(chan struct{})
go memwatch(cmd, done)
if err != nil {
panic(err)
}
cmd.Wait()
close(done)
}
func memwatch(cmd *exec.Cmd, done <-chan struct{}) {
// Reuse the reader so we don't have to close and reopen it all the time
smaps, err := os.Open(fmt.Sprintf("/proc/%d/smaps", cmd.Process.Pid))
if err != nil {
panic(err)
}
defer smaps.Close()
for {
select {
case <-done:
return
default:
fmt.Println("running")
time.Sleep(10 * time.Millisecond)
}
}
}
I'm tired. Anyone here for help, please.
答案1
得分: 1
我在一个没有SYS_PTRACE
能力的Docker容器中测试我的代码。这就是为什么会出现错误。当我为该容器添加了SYS_PTRACE
能力后,错误就消失了。
英文:
I test my code inside a docker container that doesn't have SYS_PTRACE
capability. That's why the error shows. The error was gone when I added the SYS_PTRACE
capability for that container.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论