github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-proc-fd/lib/open_fd.go (about)

     1  package mpprocfd
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/mattn/go-pipeline"
     9  )
    10  
    11  // OpenFd interface
    12  type OpenFd interface {
    13  	getNumOpenFileDesc() (map[string]uint64, error)
    14  }
    15  
    16  var openFd OpenFd
    17  
    18  // RealOpenFd struct
    19  type RealOpenFd struct {
    20  	process string
    21  }
    22  
    23  func (o RealOpenFd) getNumOpenFileDesc() (map[string]uint64, error) {
    24  	fds := make(map[string]uint64)
    25  
    26  	// Fetch all pids which contain specified process name
    27  	out, err := pipeline.Output(
    28  		[]string{"ps", "aux"},
    29  		[]string{"grep", o.process},
    30  		[]string{"grep", "-v", "grep"},
    31  		[]string{"grep", "-v", "mackerel-plugin-proc-fd"},
    32  		[]string{"awk", "{print $2}"},
    33  	)
    34  	if err != nil {
    35  		// No matching with p.Process invokes this case
    36  		return nil, err
    37  	}
    38  
    39  	// List the number of all open files beloging to each pid
    40  	for _, pid := range strings.Split(strings.TrimSpace(string(out)), "\n") {
    41  		out, err = pipeline.Output(
    42  			[]string{"ls", "-l", fmt.Sprintf("/proc/%s/fd", pid)},
    43  			[]string{"grep", "-v", "total"},
    44  			[]string{"wc", "-l"},
    45  		)
    46  		if err != nil {
    47  			// The process with pid terminates"
    48  			return nil, err
    49  		}
    50  
    51  		num, err := strconv.ParseUint(strings.TrimSpace(string(out)), 10, 32)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		fds[pid] = num
    56  	}
    57  
    58  	return fds, nil
    59  }