build(deps): bump github.com/gookit/config/v2 from 2.2.5 to 2.2.6
Bumps [github.com/gookit/config/v2](https://github.com/gookit/config) from 2.2.5 to 2.2.6. - [Release notes](https://github.com/gookit/config/releases) - [Commits](https://github.com/gookit/config/compare/v2.2.5...v2.2.6) --- updated-dependencies: - dependency-name: github.com/gookit/config/v2 dependency-version: 2.2.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
+9
-6
@@ -394,12 +394,17 @@ func (c *Cmd) Output() (string, error) {
|
||||
return "DRY-RUN: ok", nil
|
||||
}
|
||||
|
||||
output, err := c.Cmd.Output()
|
||||
bs, err := c.Cmd.Output()
|
||||
|
||||
if c.AfterRun != nil {
|
||||
c.AfterRun(c, err)
|
||||
}
|
||||
return string(output), err
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
// AllOutput run and return output, will combine stderr and stdout output
|
||||
func (c *Cmd) AllOutput() (string, error) {
|
||||
return c.CombinedOutput()
|
||||
}
|
||||
|
||||
// CombinedOutput run and return output, will combine stderr and stdout output
|
||||
@@ -412,12 +417,11 @@ func (c *Cmd) CombinedOutput() (string, error) {
|
||||
return "DRY-RUN: ok", nil
|
||||
}
|
||||
|
||||
output, err := c.Cmd.CombinedOutput()
|
||||
|
||||
bs, err := c.Cmd.CombinedOutput()
|
||||
if c.AfterRun != nil {
|
||||
c.AfterRun(c, err)
|
||||
}
|
||||
return string(output), err
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
// MustRun a command. will panic on error
|
||||
@@ -444,7 +448,6 @@ func (c *Cmd) Run() error {
|
||||
|
||||
// do running
|
||||
err := c.Cmd.Run()
|
||||
|
||||
if c.AfterRun != nil {
|
||||
c.AfterRun(c, err)
|
||||
}
|
||||
|
||||
+29
-14
@@ -1,10 +1,10 @@
|
||||
package sysutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
|
||||
"github.com/gookit/goutil/cliutil/cmdline"
|
||||
"github.com/gookit/goutil/internal/checkfn"
|
||||
"github.com/gookit/goutil/sysutil/cmdr"
|
||||
)
|
||||
|
||||
@@ -13,17 +13,19 @@ func NewCmd(bin string, args ...string) *cmdr.Cmd {
|
||||
return cmdr.NewCmd(bin, args...)
|
||||
}
|
||||
|
||||
// FlushExec instance
|
||||
// FlushExec command, will flush output to stdout,stderr
|
||||
func FlushExec(bin string, args ...string) error {
|
||||
return cmdr.NewCmd(bin, args...).FlushRun()
|
||||
}
|
||||
|
||||
// QuickExec quick exec an simple command line
|
||||
// QuickExec quick exec a simple command line, return combined output.
|
||||
func QuickExec(cmdLine string, workDir ...string) (string, error) {
|
||||
return ExecLine(cmdLine, workDir...)
|
||||
}
|
||||
|
||||
// ExecLine quick exec an command line string
|
||||
// ExecLine quick exec a command line string, return combined output.
|
||||
//
|
||||
// NOTE: not support | or ; in cmdLine
|
||||
func ExecLine(cmdLine string, workDir ...string) (string, error) {
|
||||
p := cmdline.NewParser(cmdLine)
|
||||
|
||||
@@ -33,11 +35,11 @@ func ExecLine(cmdLine string, workDir ...string) (string, error) {
|
||||
cmd.Dir = workDir[0]
|
||||
}
|
||||
|
||||
bs, err := cmd.Output()
|
||||
bs, err := cmd.CombinedOutput()
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
// ExecCmd a command and return output.
|
||||
// ExecCmd a command and return combined output.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
@@ -49,11 +51,15 @@ func ExecCmd(binName string, args []string, workDir ...string) (string, error) {
|
||||
cmd.Dir = workDir[0]
|
||||
}
|
||||
|
||||
bs, err := cmd.Output()
|
||||
bs, err := cmd.CombinedOutput()
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
// ShellExec exec command by shell cmdLine. eg: "ls -al"
|
||||
// ShellExec exec command by shell cmdLine, return combined output.
|
||||
//
|
||||
// shells e.g. "/bin/sh", "bash", "cmd", "cmd.exe", "powershell", "powershell.exe", "pwsh", "pwsh.exe"
|
||||
//
|
||||
// eg: ShellExec("ls -al")
|
||||
func ShellExec(cmdLine string, shells ...string) (string, error) {
|
||||
// shell := "/bin/sh"
|
||||
shell := "sh"
|
||||
@@ -61,12 +67,21 @@ func ShellExec(cmdLine string, shells ...string) (string, error) {
|
||||
shell = shells[0]
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
cmd := exec.Command(shell, "-c", cmdLine)
|
||||
cmd.Stdout = &out
|
||||
// "-c" for bash,sh,zsh shell
|
||||
mark := "-c"
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", err
|
||||
// special for Windows shell
|
||||
if IsWindows() {
|
||||
// use cmd.exe, mark is "/c"
|
||||
if checkfn.StringsContains([]string{"cmd", "cmd.exe"}, shell) {
|
||||
mark = "/c"
|
||||
} else if checkfn.StringsContains([]string{"powershell", "powershell.exe", "pwsh", "pwsh.exe"}, shell) {
|
||||
// "-Command" for powershell
|
||||
mark = "-Command"
|
||||
}
|
||||
}
|
||||
return out.String(), nil
|
||||
|
||||
cmd := exec.Command(shell, mark, cmdLine)
|
||||
bs, err := cmd.CombinedOutput()
|
||||
return string(bs), err
|
||||
}
|
||||
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
package sysutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/errorx"
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// OSVersionInfo 结构体用于存储操作系统版本信息
|
||||
//
|
||||
// NOTE: Windows 10 和 Windows 11 在主版本号和次版本号上是相同的,因此需要通过构建号(win11: DwBuildNumber>=22000)来进一步区分
|
||||
type OSVersionInfo struct {
|
||||
// 主版本号
|
||||
MajorVersion uint16
|
||||
// 次版本号
|
||||
MinorVersion uint16
|
||||
// 构建号
|
||||
BuildNumber uint32
|
||||
// 修订号
|
||||
RevisionNumber uint32
|
||||
}
|
||||
|
||||
// FetchOsVersion Get Windows system version information
|
||||
//
|
||||
// 还可用使用dll获取:
|
||||
//
|
||||
// 通过 GetVersion, GetVersionEx 函数获取的信息不准确. win11获取到 6.2.9200, 实际是 10.0.22631
|
||||
func FetchOsVersion() (*OSVersionInfo, error) {
|
||||
// Windows cmd 执行 ver 命令
|
||||
out, err := ShellExec("ver", "cmd")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parseOsVersionString(out)
|
||||
}
|
||||
|
||||
// IsLtWindows7 判断是否小于 Windows 7
|
||||
func (ov *OSVersionInfo) IsLtWindows7() bool {
|
||||
return ov.MajorVersion < 6 || (ov.MajorVersion == 6 && ov.MinorVersion < 1)
|
||||
}
|
||||
|
||||
// IsWindows7 判断是否为 Windows 7
|
||||
func (ov *OSVersionInfo) IsWindows7() bool {
|
||||
return ov.MajorVersion == 6 && ov.MinorVersion == 1
|
||||
}
|
||||
|
||||
// IsWindows8 判断是否为 Windows 8
|
||||
func (ov *OSVersionInfo) IsWindows8() bool {
|
||||
return ov.MajorVersion == 6 && ov.MinorVersion == 2
|
||||
}
|
||||
|
||||
// IsWindows10 判断是否为 Windows 10
|
||||
func (ov *OSVersionInfo) IsWindows10() bool {
|
||||
return ov.MajorVersion == 10 && ov.MinorVersion == 0 && ov.BuildNumber < 22000
|
||||
}
|
||||
|
||||
// IsWindows11 判断是否为 Windows 11
|
||||
func (ov *OSVersionInfo) IsWindows11() bool {
|
||||
return ov.MajorVersion == 10 && ov.MinorVersion == 0 && ov.BuildNumber >= 22000
|
||||
}
|
||||
|
||||
// Name 获取 Windows 通用的版本名称. eg: xp, win7, win8, win10, win11, unknown
|
||||
func (ov *OSVersionInfo) Name() string {
|
||||
switch ov.MajorVersion {
|
||||
case 10:
|
||||
if ov.BuildNumber < 22000 {
|
||||
return "win10"
|
||||
} else {
|
||||
return "win11"
|
||||
}
|
||||
case 6:
|
||||
switch ov.MinorVersion {
|
||||
case 0:
|
||||
return "vista"
|
||||
case 1:
|
||||
return "win7"
|
||||
case 2:
|
||||
return "win8"
|
||||
case 3:
|
||||
return "win8.1"
|
||||
}
|
||||
case 5:
|
||||
switch ov.MinorVersion {
|
||||
case 1:
|
||||
return "xp"
|
||||
case 2:
|
||||
return "ws2003" // win server 2003
|
||||
}
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// String format
|
||||
func (ov *OSVersionInfo) String() string {
|
||||
return fmt.Sprintf("%d.%d.%d", ov.MajorVersion, ov.MinorVersion, ov.BuildNumber)
|
||||
}
|
||||
|
||||
func parseOsVersionString(out string) (*OSVersionInfo, error) {
|
||||
// out eg: Microsoft Windows [Version 10.0.22631.4391] => 10.0.22631.4391
|
||||
// 部分系统会输出中文 eg: Microsoft Windows [版本 10.0.22631.4391]
|
||||
out = strings.TrimSpace(out)
|
||||
ns := strings.SplitN(out, "[", 2)
|
||||
if len(ns) < 2 {
|
||||
return nil, errorx.Rawf("cannot parse version info: %s", out)
|
||||
}
|
||||
|
||||
ns = strutil.SplitByWhitespace(strings.Trim(ns[1], "]"))
|
||||
if len(ns) < 2 {
|
||||
return nil, errorx.Rawf("cannot parse version info2: %s", out)
|
||||
}
|
||||
|
||||
var err error
|
||||
var ovi OSVersionInfo
|
||||
// get like: 10.0.22631.4391 or 10.0.22631
|
||||
verStr := ns[1]
|
||||
|
||||
if strings.Count(verStr, ".") >= 3 {
|
||||
_, err = fmt.Sscanf(verStr, "%d.%d.%d.%d", &ovi.MajorVersion, &ovi.MinorVersion, &ovi.BuildNumber, &ovi.RevisionNumber)
|
||||
} else {
|
||||
_, err = fmt.Sscanf(verStr, "%d.%d.%d", &ovi.MajorVersion, &ovi.MinorVersion, &ovi.BuildNumber)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, errorx.Rawf("parse version info %q error: %v", verStr, err)
|
||||
}
|
||||
return &ovi, nil
|
||||
}
|
||||
|
||||
// 全局变量
|
||||
var stdOv, stdErr = FetchOsVersion()
|
||||
|
||||
// OsVersion Get operating system version information
|
||||
func OsVersion() *OSVersionInfo {
|
||||
return stdOv
|
||||
}
|
||||
|
||||
// OvParseError error on parse os version info
|
||||
func OvParseError() error {
|
||||
return stdErr
|
||||
}
|
||||
+23
-2
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/gookit/goutil/internal/checkfn"
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
@@ -144,6 +145,12 @@ func EnvPaths() []string {
|
||||
return filepath.SplitList(os.Getenv("PATH"))
|
||||
}
|
||||
|
||||
// SearchPathOption settings for SearchPath
|
||||
type SearchPathOption struct {
|
||||
// 限制的扩展名
|
||||
LimitExt []string
|
||||
}
|
||||
|
||||
// SearchPath search executable files in the system $PATH
|
||||
//
|
||||
// Usage:
|
||||
@@ -154,6 +161,9 @@ func SearchPath(keywords string, limit int) []string {
|
||||
ptn := "*" + keywords + "*"
|
||||
list := make([]string, 0)
|
||||
|
||||
// if windows, will limit with .exe, .bat, .cmd
|
||||
isWindows := IsWindows()
|
||||
winExts := []string{".exe", ".bat", ".cmd"}
|
||||
checked := make(map[string]bool)
|
||||
for _, dir := range filepath.SplitList(path) {
|
||||
// Unix shell semantics: path element "" means "."
|
||||
@@ -169,10 +179,21 @@ func SearchPath(keywords string, limit int) []string {
|
||||
checked[dir] = true
|
||||
matches, err := filepath.Glob(filepath.Join(dir, ptn))
|
||||
if err == nil && len(matches) > 0 {
|
||||
list = append(list, matches...)
|
||||
size := len(list)
|
||||
if isWindows {
|
||||
// if windows, will limit with .exe, .bat, .cmd
|
||||
for _, fPath := range matches {
|
||||
fExt := filepath.Ext(fPath)
|
||||
if checkfn.StringsContains(winExts, fExt) {
|
||||
continue
|
||||
}
|
||||
list = append(list, fPath)
|
||||
}
|
||||
} else {
|
||||
list = append(list, matches...)
|
||||
}
|
||||
|
||||
// limit result size
|
||||
size := len(list)
|
||||
if limit > 0 && size >= limit {
|
||||
list = list[:limit]
|
||||
break
|
||||
|
||||
+19
-26
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/gookit/goutil/internal/comfunc"
|
||||
)
|
||||
|
||||
// MustFindUser must find an system user by name
|
||||
// MustFindUser must find a system user by name
|
||||
func MustFindUser(uname string) *user.User {
|
||||
u, err := user.Lookup(uname)
|
||||
if err != nil {
|
||||
@@ -16,14 +16,13 @@ func MustFindUser(uname string) *user.User {
|
||||
return u
|
||||
}
|
||||
|
||||
// LoginUser must get current user
|
||||
// LoginUser must get current user, will panic if error
|
||||
func LoginUser() *user.User {
|
||||
return CurrentUser()
|
||||
}
|
||||
|
||||
// CurrentUser must get current user
|
||||
// CurrentUser must get current user, will panic if error
|
||||
func CurrentUser() *user.User {
|
||||
// check $HOME/.terminfo
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -31,9 +30,8 @@ func CurrentUser() *user.User {
|
||||
return u
|
||||
}
|
||||
|
||||
// UHomeDir get user home dir path.
|
||||
// UHomeDir get user home dir path, ignore error. (by user.Current)
|
||||
func UHomeDir() string {
|
||||
// check $HOME/.terminfo
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return ""
|
||||
@@ -42,37 +40,32 @@ func UHomeDir() string {
|
||||
}
|
||||
|
||||
// homeDir cache
|
||||
var homeDir string
|
||||
var _homeDir string
|
||||
|
||||
// UserHomeDir is alias of os.UserHomeDir, but ignore error
|
||||
// UserHomeDir is alias of os.UserHomeDir, but ignore error.(by os.UserHomeDir)
|
||||
func UserHomeDir() string {
|
||||
if homeDir == "" {
|
||||
homeDir, _ = os.UserHomeDir()
|
||||
if _homeDir == "" {
|
||||
_homeDir, _ = os.UserHomeDir()
|
||||
}
|
||||
return homeDir
|
||||
return _homeDir
|
||||
}
|
||||
|
||||
// HomeDir get user home dir path.
|
||||
func HomeDir() string {
|
||||
return UserHomeDir()
|
||||
func HomeDir() string { return UserHomeDir() }
|
||||
|
||||
// UserDir will prepend user home dir to subPaths
|
||||
func UserDir(subPaths ...string) string {
|
||||
return comfunc.JoinPaths2(UserHomeDir(), subPaths)
|
||||
}
|
||||
|
||||
// UserDir will prepend user home dir to subPath
|
||||
func UserDir(subPath string) string {
|
||||
dir := UserHomeDir()
|
||||
return dir + "/" + subPath
|
||||
}
|
||||
|
||||
// UserCacheDir will prepend user `$HOME/.cache` to subPath
|
||||
func UserCacheDir(subPath string) string {
|
||||
dir := UserHomeDir()
|
||||
return dir + "/.cache/" + subPath
|
||||
// UserCacheDir will prepend user `$HOME/.cache` to subPaths
|
||||
func UserCacheDir(subPaths ...string) string {
|
||||
return comfunc.JoinPaths3(UserHomeDir(), ".cache", subPaths)
|
||||
}
|
||||
|
||||
// UserConfigDir will prepend user `$HOME/.config` to subPath
|
||||
func UserConfigDir(subPath string) string {
|
||||
dir := UserHomeDir()
|
||||
return dir + "/.config/" + subPath
|
||||
func UserConfigDir(subPaths ...string) string {
|
||||
return comfunc.JoinPaths3(UserHomeDir(), ".config", subPaths)
|
||||
}
|
||||
|
||||
// ExpandPath will parse `~` as user home dir path.
|
||||
|
||||
+6
@@ -3,11 +3,17 @@
|
||||
package sysutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/gookit/goutil/strutil"
|
||||
)
|
||||
|
||||
// IsAdmin Determine whether the current user is an administrator(root)
|
||||
func IsAdmin() bool {
|
||||
return os.Getuid() == 0
|
||||
}
|
||||
|
||||
// ChangeUserByName change work user by new username.
|
||||
func ChangeUserByName(newUname string) error {
|
||||
u := MustFindUser(newUname)
|
||||
|
||||
+7
@@ -19,3 +19,10 @@ func ChangeUserUidGid(newUid int, newGid int) (err error) {
|
||||
func ChangeUserUIDGid(newUid int, newGid int) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsAdmin Determine whether the current user is an administrator
|
||||
func IsAdmin() bool {
|
||||
// 执行 net session 判断
|
||||
_, err := ExecCmd("net", []string{"session"})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user