package executor import ( "bufio" "bytes" "fmt" "io" "os" "os/exec" "strings" ) var RemoveForcePrefix = []string{"rm", "-rf"} // BasicCommandExists 判定命令是否存在 func BasicCommandExists(commandName string) bool { cmd := exec.Command("command", "-v", commandName) err := cmd.Run() if err != nil { log.DebugF("指令 %s 不存在 => %s", commandName, err.Error()) return false } else { return true } } // BasicCommandExistsBatch 判定批量命令是否存在 func BasicCommandExistsBatch(commandNameList []string) (bool, string) { for _, commandName := range commandNameList { if !BasicCommandExists(commandName) { return false, commandName } } return true, "" } // BasicCommandExistByPath 根据路径判定 命令是否存在 func BasicCommandExistByPath(commandName string) bool { if BasicFileExistInFolder(commandName, "/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "bin", "/snap/bin") { return true } return false } // BasicFileExistInFolder 查询fileName是否存在于目录folderList中,如果存在返回true,不存在返回false func BasicFileExistInFolder(fileName string, folderList ...string) bool { for _, folder := range folderList { if BasicFolderExists(folder) { // is folder ok, _ := PipelineCommandExecutor([][]string{ { "ls", folder, }, { "grep", "-c", fileName, }, }) if ok { return true } } else { // it's a file ok, _ := PipelineCommandExecutor([][]string{ { "echo", folder, }, { "grep", "-c", fileName, }, }) if ok { return true } } } return false } func BasicGrepItemInFile(item string, fileName string) bool { if !BasicFileExistAndNotNull(fileName) { log.ErrorF("[BasicGrepItemInFile] - fileName [ %s ] not exits !", fileName) return false } ok, _ := PipelineCommandExecutor([][]string{ { "cat", fileName, }, { "grep", "-q", item, }, }) if ok { return true } return false } func BasicFindContentInFile(content string, fileName string) bool { // Open the file file, err := os.Open(fileName) if err != nil { log.ErrorF("[BasicFindContentInFile] - file not exits !") return false } defer file.Close() // Create a scanner to read the file line by line scanner := bufio.NewScanner(file) // Set the split function for the scanner scanner.Split(bufio.ScanLines) // Iterate over the lines of the file for scanner.Scan() { // Get the current line line := scanner.Text() // Check if the current line contains the search term if strings.Contains(line, content) { return true } } // Check for any errors that occurred during scanning if err := scanner.Err(); err != nil { log.ErrorF("[BasicFindContentInFile] - scanner error ! %s", err.Error()) } return false } func BasicFindDeleteContendLineInFile(content string, fileName string) bool { // Open the file file, err := os.Open(fileName) if err != nil { log.ErrorF("[FindDeleteContendLineInFile] - file not exits !") return false } defer file.Close() // Create a scanner to read the file line by line scanner := bufio.NewScanner(file) // Set the split function for the scanner scanner.Split(bufio.ScanLines) // 创建一个新的文件内容变量 var newContent string // Iterate over the lines of the file for scanner.Scan() { // Get the current line line := scanner.Text() // Check if the current line contains the search term if !strings.Contains(line, content) { newContent += line + "\n" } } // Check for any errors that occurred during scanning if err := scanner.Err(); err != nil { log.ErrorF("[BasicFindContentInFile] - scanner error ! %s", err.Error()) return false } // 将修改后的内容写回文件 err = os.WriteFile(fileName, []byte(newContent), os.ModePerm) if err != nil { log.ErrorF("[FindDeleteContendLineInFile] - write file %s error with contend %s", fileName, newContent) return false } return true } func BasicDockerImageExists(imageName, imageVersion string) bool { if !BasicCommandExistByPath("docker") { return false } ok, _ := PipelineCommandExecutor([][]string{ { "docker", "image", "ls", }, { "grep", imageName, }, { "grep", "-q", imageVersion, }, }) if !ok { return false } return true } func BasicInstallSoftwares(installPrefix []string, isStrict bool, softwares ...string) (bool, []string) { var installLog []string for _, software := range softwares { log.DebugF("[BasicInstallSoftwares] - going to install [ %s ]", software) if !PureResultSingleExecute(append(installPrefix, software)) { failedInstall := fmt.Sprintf("[BasicInstallSoftwares] - software of [ %s ] install failed !", software) installLog = append(installLog, failedInstall) if isStrict { return false, installLog } } successInstall := fmt.Sprintf("[BasicInstallSoftwares] - software of [ %s ] install success !", software) installLog = append(installLog, successInstall) } return true, installLog } // BasicReplace 基础替换命令 func BasicReplace(filename string, origin string, replace string) bool { // 暂不添加 //if !BasicFileExistAndNotNull(filename) { // log.DebugF("文件替换") //} cmd := exec.Command("sed", "-i", "s/"+origin+"/"+replace+"/g", filename) err := cmd.Run() if err != nil { log.DebugF("替换文件 %s ,从 [%s] => [%s] 错误!", filename, origin, replace) return false } else { return true } } func BasicRemoveFolderComplete(folderName string) bool { if !BasicFileExists(folderName) || !BasicFolderExists(folderName) { log.DebugF("[BasicRemoveFolderComplete] - file or folder of [%s] not exists !", folderName) return true } cmd := exec.Command("rm", "-rf", folderName) err := cmd.Run() if err != nil { log.DebugF("删除 %s 失败!", folderName) return false } else { return true } } // BasicFileExists 检测文件是否存在 func BasicFileExists(filename string) bool { cmd := exec.Command("test", "-f", filename) err := cmd.Run() if err != nil { log.DebugF("文件 %s 不存在!", filename) return false } else { return true } } // BasicFileExistAndNotNull 文件不为空返回true 文件为空返回false func BasicFileExistAndNotNull(filename string) bool { cmd := exec.Command("test", "-s", filename) err := cmd.Run() if err != nil { log.DebugF("文件 %s 为空!", filename) return false } else { return true } } func BasicFolderExists(folderName string) bool { cmd := exec.Command("test", "-d", folderName) err := cmd.Run() if err != nil { log.DebugF("目录 %s 不存在!", folderName) return false } else { return true } } func BasicCreateFolder(folderName string) bool { cmd := exec.Command("test", "-d", folderName) err := cmd.Run() if err == nil { log.DebugF("folder %s already exists !", folderName) return true } cmd2 := exec.Command("mkdir", "-p", folderName) err = cmd2.Run() if err != nil { log.ErrorF("folder %s create error!", folderName) return false } else { log.DebugF("folder %s create success!", folderName) return true } } // BasicPrettyPrint 打印执行结果 func BasicPrettyPrint(resultOk bool, resultLog []string) { fmt.Printf("resultOK is => %#v\n", resultOk) if resultLog == nil || len(resultLog) == 0 { return } for _, s := range resultLog { fmt.Println(s) fmt.Println() } } // BasicSystemdShutdown 使用Systemd关闭服务,会判定服务器是否存在 func BasicSystemdShutdown(serviceName string) (ok bool, resultLog []string) { if !strings.HasSuffix(serviceName, ".service") { serviceName = serviceName + ".service" } // 检查是否存在 existService := BasicFileExistInFolder(serviceName, "/lib/systemd/system/", "/etc/systemd/system") if !existService { return true, []string{ serviceName, "该服务不存在!", } } // 关闭 var shutDownCommand = [][]string{ { "systemctl", "stop", serviceName, }, { "sleep", "1", }, { "systemctl", "disable", serviceName, }, } resultOK := PureResultSingleExecuteBatch(shutDownCommand) return resultOK, resultLog } // BasicSystemdUp 使用Systemd启动服务,会判定服务器是否存在 func BasicSystemdUp(serviceName string) (ok bool, resultLog []string) { if !strings.HasSuffix(serviceName, ".service") { serviceName = serviceName + ".service" } // 检查是否存在 existService := BasicFileExistInFolder(serviceName, "/lib/systemd/system/", "/etc/systemd/system") if !existService { return true, []string{ serviceName, "该服务不存在!", } } // 关闭 var shutDownCommand = [][]string{ { "systemctl", "start", serviceName, }, { "sleep", "1", }, { "systemctl", "enable", serviceName, }, } resultOK := PureResultSingleExecuteBatch(shutDownCommand) return resultOK, resultLog } // BasicTransPipelineCommand 转换手写的管道命令为可执行的形式 func BasicTransPipelineCommand(pipelineString string) (pipelineCommand [][]string) { var pipelineCommandC [][]string split := strings.Split(pipelineString, "|") if len(split) == 0 { log.WarnF("输入的pipelineString有误! %s", pipelineString) return pipelineCommandC } for _, s := range split { // 去除掉无效的空行 singleCommand := strings.Split(s, " ") var realSingleCommand []string for i := range singleCommand { if singleCommand[i] != "" { realSingleCommand = append(realSingleCommand, singleCommand[i]) } } pipelineCommandC = append(pipelineCommandC, realSingleCommand) } return pipelineCommandC } func BasicConvertBufferToSlice(outputBuffer bytes.Buffer) (resultLog []string) { s := outputBuffer.String() split := strings.Split(s, "\n") return split } // BasicDownloadFile 从目标地址下载文件到目的地,并检测文件是否下载成功 func BasicDownloadFile(downloadUrl, desFile string) (downloadOk bool, resultLog []string) { // wget or curl download var ok bool if BasicCommandExistByPath("wget") { ok, resultLog = AllCommandExecutor([]string{ "wget", "--no-check-certificate", "--timeout=5", downloadUrl, "-qO", desFile, }) } else if BasicCommandExistByPath("curl") { ok, resultLog = AllCommandExecutor([]string{ "curl", "-o", desFile, "--insecure", "--max-time", "5", downloadUrl, }) } else { sprintf := fmt.Sprintf("[BasicDownloadFile] - neither wget or curl exists ! can't download file [ %s ] from [ %s ]", desFile, downloadUrl) log.Error(sprintf) return false, []string{ sprintf, } } errLog := fmt.Sprintf("[BasicDownloadFile] - download file [ %s ] from [ %s ] failed !", desFile, downloadUrl) if !ok { log.Error(errLog) return false, []string{ errLog, } } // check file exists existAndNotNull := BasicFileExistAndNotNull(desFile) if !existAndNotNull { return false, []string{ errLog, "[BasicDownloadFile] - file not exist !", } } return true, nil } // BasicAppendSourceToFile 将源文件的内容添加到目标文件,使用golang标准库完成,跨平台、安全性更强 func BasicAppendSourceToFile(sourceFile, targetFile string) bool { // 打开源文件 source, err := os.Open(sourceFile) if err != nil { log.ErrorF("[BasicAppendSourceToFile] - error open source file => %s, error is %s", sourceFile, err.Error()) return false } defer source.Close() // 打开目标文件,如果不存在则创建,如果存在则在末尾追加 target, err := os.OpenFile(targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.ErrorF("[BasicAppendSourceToFile] - error open target file => %s, error is %s", sourceFile, err.Error()) return false } defer target.Close() // 将源文件内容复制到目标文件 _, err = io.Copy(target, source) if err != nil { log.ErrorF("[BasicAppendSourceToFile] - Error appending to target file: %s", err.Error()) return false } return true } // BasicAppendContentToFile 向目标文件中追加写入一些内容 func BasicAppendContentToFile(content string, targetFile string) bool { // 打开文件用于追加。如果文件不存在,将会创建一个新文件。 file, err := os.OpenFile(targetFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.ErrorF("[BasicAppendContentToFile] - Error opening file: %s , error is %s", targetFile, err.Error()) return false } defer file.Close() // 确保文件最终被关闭 // 写入内容到文件 if _, err := file.WriteString(content); err != nil { log.ErrorF("[BasicAppendContentToFile] - Error writing to file: %s , error is %s", targetFile, err.Error()) return false } return true } // BasicAppendNullToFile 清空一个文件 func BasicAppendNullToFile(targetFile string) bool { // 使用os.O_TRUNC清空文件内容 file, err := os.OpenFile(targetFile, os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { log.ErrorF("[BasicAppendNullToFile] - Error opening file: %s, error is %s", targetFile, err.Error()) return false } defer file.Close() // 确保在函数退出前关闭文件 return true } func BasicWordSpaceCompletion(source string, totalLength int) string { sourceLength := len(source) if sourceLength >= totalLength { return source } for i := 0; i < totalLength-sourceLength; i++ { source += " " } return source }