feat(inputs.processes): Add `use_sudo` option for BSD (#12628)
This commit is contained in:
parent
7345b400ff
commit
64033bd393
|
|
@ -22,7 +22,9 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
```toml @sample.conf
|
```toml @sample.conf
|
||||||
# Get the number of processes and group them by status
|
# Get the number of processes and group them by status
|
||||||
[[inputs.processes]]
|
[[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
|
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`
|
`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
|
## Metrics
|
||||||
|
|
||||||
- processes
|
- processes
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Processes struct {
|
type Processes struct {
|
||||||
execPS func() ([]byte, error)
|
UseSudo bool `toml:"use_sudo"`
|
||||||
|
|
||||||
|
execPS func(UseSudo bool) ([]byte, error)
|
||||||
readProcFile func(filename string) ([]byte, error)
|
readProcFile func(filename string) ([]byte, error)
|
||||||
|
|
||||||
Log telegraf.Logger
|
Log telegraf.Logger
|
||||||
|
|
@ -87,7 +89,7 @@ func getEmptyFields() map[string]interface{} {
|
||||||
|
|
||||||
// exec `ps` to get all process states
|
// exec `ps` to get all process states
|
||||||
func (p *Processes) gatherFromPS(fields map[string]interface{}) error {
|
func (p *Processes) gatherFromPS(fields map[string]interface{}) error {
|
||||||
out, err := p.execPS()
|
out, err := p.execPS(p.UseSudo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -208,13 +210,18 @@ func readProcFile(filename string) ([]byte, error) {
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func execPS() ([]byte, error) {
|
func execPS(useSudo bool) ([]byte, error) {
|
||||||
bin, err := exec.LookPath("ps")
|
bin, err := exec.LookPath("ps")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,8 +172,8 @@ func TestParkedProcess(t *testing.T) {
|
||||||
testutil.IgnoreTime())
|
testutil.IgnoreTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExecPS(out string) func() ([]byte, error) {
|
func testExecPS(out string) func(_ bool) ([]byte, error) {
|
||||||
return func() ([]byte, error) { return []byte(out), nil }
|
return func(_ bool) ([]byte, error) { return []byte(out), nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct for counting calls to testProcFile
|
// 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
|
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")
|
return []byte("\nSTAT\nD\nI\nL\nR\nR+\nS\nS+\nSNs\nSs\nU\nZ\n"), fmt.Errorf("error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
# Get the number of processes and group them by status
|
# Get the number of processes and group them by status
|
||||||
[[inputs.processes]]
|
[[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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue