506 lines
11 KiB
Go
506 lines
11 KiB
Go
package executor
|
||
|
||
import (
|
||
"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 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
|
||
}
|