diff --git a/go.mod b/go.mod index 380fb49..09a4bef 100644 --- a/go.mod +++ b/go.mod @@ -39,4 +39,5 @@ require ( golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 golang.org/x/tools v0.1.7 // indirect gorm.io/gorm v1.24.0 + gotest.tools v2.2.0+incompatible ) diff --git a/main.go b/main.go index 7f747c7..6fe39b9 100644 --- a/main.go +++ b/main.go @@ -9,11 +9,13 @@ import ( "time" "github.com/IceWhaleTech/CasaOS-Common/model" + "github.com/IceWhaleTech/CasaOS-Common/utils/constants" "github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS/model/notify" "github.com/IceWhaleTech/CasaOS/pkg/cache" "github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/sqlite" + "github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/service" @@ -140,6 +142,10 @@ func main() { ) } + // run any script that needs to be executed + scriptDirectory := filepath.Join(constants.DefaultConfigPath, "start.d") + command.ExecuteScripts(scriptDirectory) + if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { logger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err)) } else if supported { diff --git a/pkg/utils/command/command_helper.go b/pkg/utils/command/command_helper.go index a47b288..703a8b4 100644 --- a/pkg/utils/command/command_helper.go +++ b/pkg/utils/command/command_helper.go @@ -5,7 +5,10 @@ import ( "context" "fmt" "io/ioutil" + "os" "os/exec" + "path/filepath" + "strings" "time" ) @@ -111,3 +114,53 @@ func ExecSmartCTLByPath(path string) []byte { func ExecEnabledSMART(path string) { exec.Command("smartctl", "-s on", path).Output() } + +func ExecuteScripts(scriptDirectory string) { + if _, err := os.Stat(scriptDirectory); os.IsNotExist(err) { + fmt.Printf("No post-start scripts at %s\n", scriptDirectory) + return + } + + files, err := os.ReadDir(scriptDirectory) + if err != nil { + fmt.Printf("Failed to read from script directory %s: %s\n", scriptDirectory, err.Error()) + return + } + + for _, file := range files { + if file.IsDir() { + continue + } + + scriptFilepath := filepath.Join(scriptDirectory, file.Name()) + + f, err := os.Open(scriptFilepath) + if err != nil { + fmt.Printf("Failed to open script file %s: %s\n", scriptFilepath, err.Error()) + continue + } + f.Close() + + scanner := bufio.NewScanner(f) + scanner.Scan() + shebang := scanner.Text() + + interpreter := "/bin/sh" + if strings.HasPrefix(shebang, "#!") { + interpreter = shebang[2:] + } + + cmd := exec.Command(interpreter, scriptFilepath) + + fmt.Printf("Executing post-start script %s using %s\n", scriptFilepath, interpreter) + + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + err = cmd.Run() + if err != nil { + fmt.Printf("Failed to execute post-start script %s: %s\n", scriptFilepath, err.Error()) + } + } + fmt.Println("Finished executing post-start scripts.") +} diff --git a/pkg/utils/command/command_helper_test.go b/pkg/utils/command/command_helper_test.go new file mode 100644 index 0000000..713ea0c --- /dev/null +++ b/pkg/utils/command/command_helper_test.go @@ -0,0 +1,29 @@ +package command + +import ( + "os" + "testing" + + "gotest.tools/assert" +) + +func TestExecuteScripts(t *testing.T) { + // make a temp directory + tmpDir, err := os.MkdirTemp("", "casaos-test-*") + assert.NilError(t, err) + defer os.RemoveAll(tmpDir) + + ExecuteScripts(tmpDir) + + // create a sample script under tmpDir + script := tmpDir + "/test.sh" + f, err := os.Create(script) + assert.NilError(t, err) + defer f.Close() + + // write a sample script + _, err = f.WriteString("#!/bin/bash\necho 123") + assert.NilError(t, err) + + ExecuteScripts(tmpDir) +}