feat(inputs.processes): Add `use_sudo` option for BSD (#12628)

This commit is contained in:
Joshua Powers 2023-02-06 14:00:21 -07:00 committed by GitHub
parent 7345b400ff
commit 64033bd393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 9 deletions

View File

@ -22,7 +22,9 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
```toml @sample.conf
# Get the number of processes and group them by status
[[inputs.processes]]
# no configuration
## Use sudo to run ps command on *BSD systems. Linux systems will read
## /proc, so this does not apply there.
use_sudo = false
```
Another possible configuration is to define an alternative path for resolving
@ -31,6 +33,28 @@ retrieve process information from the specified location.
`docker run -v /proc:/rootfs/proc:ro -e HOST_PROC=/rootfs/proc`
### Using sudo
Linux systems will read from `/proc`, while BSD systems will use the `ps`
command. The `ps` command generally does not require elevated permissions.
However, if a user wants to collect system-wide stats, elevated permissions are
required. If the user has configured sudo with the ability to run this
command, then set the `use_sudo` to true.
If your account does not already have the ability to run commands with
passwordless sudo then updates to the sudoers file are required. Below is an
example to allow the requires ps commands:
First, use the `visudo` command to start editing the sudoers file. Then add
the following content, where `<username>` is the username of the user that
needs this access:
```text
Cmnd_Alias PS = /bin/ps
<username> ALL=(root) NOPASSWD: PS
Defaults!PS !logfile, !syslog, !pam_session
```
## Metrics
- processes

View File

@ -18,7 +18,9 @@ import (
)
type Processes struct {
execPS func() ([]byte, error)
UseSudo bool `toml:"use_sudo"`
execPS func(UseSudo bool) ([]byte, error)
readProcFile func(filename string) ([]byte, error)
Log telegraf.Logger
@ -87,7 +89,7 @@ func getEmptyFields() map[string]interface{} {
// exec `ps` to get all process states
func (p *Processes) gatherFromPS(fields map[string]interface{}) error {
out, err := p.execPS()
out, err := p.execPS(p.UseSudo)
if err != nil {
return err
}
@ -208,13 +210,18 @@ func readProcFile(filename string) ([]byte, error) {
return data, nil
}
func execPS() ([]byte, error) {
func execPS(useSudo bool) ([]byte, error) {
bin, err := exec.LookPath("ps")
if err != nil {
return nil, err
}
out, err := exec.Command(bin, "axo", "state").Output()
cmd := []string{bin, "axo", "state"}
if useSudo {
cmd = append([]string{"sudo", "-n"}, cmd...)
}
out, err := exec.Command(cmd[0], cmd[1:]...).Output()
if err != nil {
return nil, err
}

View File

@ -172,8 +172,8 @@ func TestParkedProcess(t *testing.T) {
testutil.IgnoreTime())
}
func testExecPS(out string) func() ([]byte, error) {
return func() ([]byte, error) { return []byte(out), nil }
func testExecPS(out string) func(_ bool) ([]byte, error) {
return func(_ bool) ([]byte, error) { return []byte(out), nil }
}
// struct for counting calls to testProcFile
@ -191,7 +191,7 @@ func (t *tester) testProcFile2(_ string) ([]byte, error) {
return []byte(fmt.Sprintf(testProcStat2, "S", "2")), nil
}
func testExecPSError() ([]byte, error) {
func testExecPSError(_ bool) ([]byte, error) {
return []byte("\nSTAT\nD\nI\nL\nR\nR+\nS\nS+\nSNs\nSs\nU\nZ\n"), fmt.Errorf("error")
}

View File

@ -1,3 +1,5 @@
# Get the number of processes and group them by status
[[inputs.processes]]
# no configuration
## Use sudo to run ps command on *BSD systems. Linux systems will read
## /proc, so this does not apply there.
use_sudo = false