pkg.re/essentialkaos/ek.v11@v12.41.0+incompatible/pid/pid.go (about)

     1  // Package pid provides methods for working with PID files
     2  package pid
     3  
     4  // ////////////////////////////////////////////////////////////////////////////////// //
     5  //                                                                                    //
     6  //                         Copyright (c) 2022 ESSENTIAL KAOS                          //
     7  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     8  //                                                                                    //
     9  // ////////////////////////////////////////////////////////////////////////////////// //
    10  
    11  import (
    12  	"errors"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"os"
    16  	"strconv"
    17  	"strings"
    18  
    19  	"pkg.re/essentialkaos/ek.v12/fsutil"
    20  )
    21  
    22  // ////////////////////////////////////////////////////////////////////////////////// //
    23  
    24  // Dir is a path to directory with PID files
    25  var Dir = "/var/run"
    26  
    27  // ////////////////////////////////////////////////////////////////////////////////// //
    28  
    29  // Create creates file with process PID file
    30  func Create(name string) error {
    31  	err := checkPIDDir(Dir, true)
    32  
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	if name == "" {
    38  		return errors.New("PID file name can't be blank")
    39  	}
    40  
    41  	pidFile := Dir + "/" + normalizePIDFilename(name)
    42  
    43  	if fsutil.IsExist(pidFile) {
    44  		os.Remove(pidFile)
    45  	}
    46  
    47  	return ioutil.WriteFile(
    48  		pidFile,
    49  		[]byte(fmt.Sprintf("%d\n", os.Getpid())),
    50  		0644,
    51  	)
    52  }
    53  
    54  // Remove removes file with process PID file
    55  func Remove(name string) error {
    56  	err := checkPIDDir(Dir, true)
    57  
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	pidFile := Dir + "/" + normalizePIDFilename(name)
    63  
    64  	return os.Remove(pidFile)
    65  }
    66  
    67  // Get returns PID from PID file
    68  func Get(name string) int {
    69  	err := checkPIDDir(Dir, false)
    70  
    71  	if err != nil {
    72  		return -1
    73  	}
    74  
    75  	pidFile := Dir + "/" + normalizePIDFilename(name)
    76  
    77  	return Read(pidFile)
    78  }
    79  
    80  // Read just reads PID from PID file
    81  func Read(pidFile string) int {
    82  	data, err := ioutil.ReadFile(pidFile)
    83  
    84  	if err != nil {
    85  		return -1
    86  	}
    87  
    88  	pid, err := strconv.Atoi(strings.TrimRight(string(data), "\n"))
    89  
    90  	if err != nil {
    91  		return -1
    92  	}
    93  
    94  	return pid
    95  }
    96  
    97  // ////////////////////////////////////////////////////////////////////////////////// //
    98  
    99  // checkPIDDir checks directory path and return error if directory not ok
   100  func checkPIDDir(path string, requireModify bool) error {
   101  	switch {
   102  	case !fsutil.IsExist(path):
   103  		return errors.New("Directory " + path + " does not exist")
   104  
   105  	case !fsutil.IsDir(path):
   106  		return errors.New(path + " is not directory")
   107  
   108  	case !fsutil.IsWritable(path) && requireModify:
   109  		return errors.New("Directory " + path + " is not writable")
   110  
   111  	case !fsutil.IsReadable(path):
   112  		return errors.New("Directory " + path + " is not readable")
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  // normalizePIDFilename returns PID file name with extension
   119  func normalizePIDFilename(name string) string {
   120  	if !strings.Contains(name, ".pid") {
   121  		return name + ".pid"
   122  	}
   123  
   124  	return name
   125  }