Files
ProjectOctopus/agent-go/a_executor/BasicFunction.go
2024-03-29 11:39:14 +08:00

684 lines
15 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package a_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 BasicFindAndDeleteContendLineInFile(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 BasicFindContentInCommandOutput(hardCodeCommand string, content string) (bool, []string) {
ok, resultLog := HardCodeCommandExecutor(hardCodeCommand)
if !ok {
log.ErrorF("[BasicFindContentInCommandOutput] - command error ! => %v", resultLog)
return false, nil
}
return BasicFindContentInList(content, resultLog), resultLog
}
func BasicFindContentInList(content string, list []string) bool {
for _, item := range list {
if strings.Contains(item, content) {
return true
}
}
return false
}
func BasicDockerImageExistByFullName(imageFullName string) bool {
var imageVersion string
split := strings.Split(imageFullName, ":")
imageVersion = split[len(split)-1]
imageFullName = strings.TrimSuffix(imageFullName, ":"+imageVersion)
//log.DebugF("[BasicDockerImageExistByFullName] -- %s %s", imageFullName, imageVersion)
return BasicDockerImageExists(imageFullName, imageVersion)
}
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 {
// 检查目录是否存在
if _, err := os.Stat(folderName); os.IsNotExist(err) {
// 目录不存在,创建目录
err := os.MkdirAll(folderName, os.ModePerm)
if err != nil {
// 如果创建目录失败返回false
return false
}
}
// 目录存在或者成功创建返回true
return true
}
func BasicRemoveFileOrFolder(folderName string) bool {
// Check if the folder exists
if _, err := os.Stat(folderName); os.IsNotExist(err) {
return true // folder does not exist
}
// Folder exists, remove it
err := os.Remove(folderName)
if err != nil {
// Handle error
return false
}
return true // folder was removed
}
// 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
}
func BasicDownloadFileWithProxy(downloadUrl, proxyUrl, desFile string) (downloadOk bool, resultLog []string) {
var ok bool
if !BasicCommandExistByPath("curl") {
return false, []string{
"curl not exits!",
}
}
ok, resultLog = AllCommandExecutor([]string{
"curl",
"-x",
proxyUrl,
"-o",
desFile,
"--insecure",
"--max-time",
"5",
downloadUrl,
})
errLog := fmt.Sprintf("[BasicDownloadFileWithProxy] - download file [ %s ] with proxy [ %s ] from [ %s ] failed !", desFile, proxyUrl, 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
}