Fixes Changes and new additions

Fixed an issue where launching server w/o screen failed
New: added an output showing screen sessions after launching
New: added stdout and stdin to screenless launch allowing interacting with server cli
Change: Broke up source code to make it easier to read and make changes
Change: Updated .gitignore
This commit is contained in:
2026-01-13 10:51:18 -07:00
parent 3406ab4743
commit b2c534f29b
7 changed files with 134 additions and 111 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.vscode
factorio-headless_linux_2.0.72

33
backup.go Normal file
View File

@@ -0,0 +1,33 @@
package main
import (
"fmt"
"os/exec"
"time"
)
func backUp(cmd string, c GoConfig) {
switch cmd {
case "full":
fmt.Println("Starting full server backup")
t := time.Now()
timeStamp := t.Format(time.RFC3339)
fullBackupName := fmt.Sprintf("%s/ServerBackup.%s.tgz", c.Config.BackupDir, timeStamp)
fullBackup := exec.Command("tar", "-czf", fullBackupName, c.Config.ServDir)
err := fullBackup.Run()
if err != nil {
fmt.Printf("Backup Failed: %s\n", err)
}
case "saves":
fmt.Println("Backing up saves")
t := time.Now()
timeStamp := t.Format(time.RFC3339)
savesBackupName := fmt.Sprintf("%s/SaveBackup.%s.tgz", c.Config.BackupDir, timeStamp)
saveDir := fmt.Sprintf("%s/saves", c.Config.ServDir)
savesBackup := exec.Command("tar", "-czf", savesBackupName, saveDir)
err := savesBackup.Run()
if err != nil {
fmt.Printf("Backup Failed: %s\n", err)
}
}
}

38
config.go Normal file
View File

@@ -0,0 +1,38 @@
package main
import (
"log"
"os"
"gopkg.in/yaml.v3"
)
const fmConfig = "config.yml"
type GoConfig struct {
Config struct {
ServDir string `yaml:"serverFolder"`
ServPort int `yaml:"port"`
WorldFile string `yaml:"worldFile"`
ServCfg string `yaml:"serverSettings"`
ServExec string `yaml:"serverExec"`
BackupDir string `yaml:"backupDir"`
UseScreen bool `yaml:"screen"`
ScreenName string `yaml:"screenName"`
} `yaml:"server"`
}
func readCfg(factCfg string) GoConfig {
//read config file (YAML)
fileBytes, err := os.ReadFile(factCfg)
if err != nil {
log.Fatalf("Error reading config file: %v", err)
}
// return Struct
var config GoConfig
err = yaml.Unmarshal(fileBytes, &config)
if err != nil {
log.Fatalf("Error unmarshalling YAML file: %v", err)
}
return config
}

View File

@@ -1,9 +1,9 @@
server:
serverFolder: "factorio"
serverFolder: "./factorio-headless_linux_2.0.72/factorio"
port: 34197
worldFile: "factorio/newworld.zip"
serverSettings: "factorio/data/server-settings.json"
backupDir: "backups"
serverExec: "factorio/bin/x64/factorio"
worldFile: "./factorio-headless_linux_2.0.72/factorio/Newworlds.zip"
serverSettings: "./factorio-headless_linux_2.0.72/factorio/data/server-settings.json"
backupDir: "./factorio-headless_linux_2.0.72/backups"
serverExec: "./factorio-headless_linux_2.0.72/factorio/bin/x64/factorio"
screen: True
screenName: "Factorio"
screenName: "Factorio"

Binary file not shown.

55
launchserver.go Normal file
View File

@@ -0,0 +1,55 @@
package main
import (
"fmt"
"log"
"os"
"os/exec"
"time"
)
func startStopServer(cmd string, con GoConfig) {
switch cmd {
case "start":
x := fmt.Sprintf("%s --port %d --server-settings %s --start-server %s", con.Config.ServExec, con.Config.ServPort, con.Config.ServCfg, con.Config.WorldFile)
if con.Config.UseScreen { // if screen enabled in confing.yml
fmt.Println("Starting factorio server in screen session")
startScreenCmd := exec.Command("screen", "-dmS", con.Config.ScreenName, "bash", "-c", x, "; exec sh")
startScreenCmd.Stdout = os.Stdout
startScreenCmd.Stderr = os.Stderr
err := startScreenCmd.Run()
if err != nil {
log.Fatalf("Failed to start server: %s", err)
} else {
fmt.Printf("Started server on port %d, in screen named %s\n", con.Config.ServPort, con.Config.ScreenName)
y := exec.Command("screen", "-ls")
y.Stdout = os.Stdout
y.Stderr = os.Stderr
err = y.Run()
}
} else {
startSrvCmd := exec.Command("bash", "-c", x)
startSrvCmd.Stdout = os.Stdout
startSrvCmd.Stderr = os.Stdout
startSrvCmd.Stdin = os.Stdin
err := startSrvCmd.Run()
if err != nil {
log.Fatalf("Failed to start server: %s", err)
}
}
case "stop":
quitServerCmd := exec.Command("screen", "-S", con.Config.ScreenName, "-p", "0", "-X", "stuff", "/quit\n")
err := quitServerCmd.Run()
if err != nil {
log.Fatalf("Command failed: %s, Error: %v", quitServerCmd.Args, err)
} else {
fmt.Printf("Server in screen %s stopped\n", con.Config.ScreenName)
}
fmt.Println("Waiting for server to shutdown\r")
time.Sleep(10 * time.Second)
y := exec.Command("screen", "-ls")
y.Stdout = os.Stdout
y.Stderr = os.Stderr
err = y.Run()
}
}

105
main.go
View File

@@ -2,114 +2,9 @@ package main
import (
"fmt"
"log"
"os"
"os/exec"
"time"
"gopkg.in/yaml.v3"
)
const fmConfig = "config.yml"
type GoConfig struct {
Config struct {
ServDir string `yaml:"serverFolder"`
ServPort int `yaml:"port"`
WorldFile string `yaml:"worldFile"`
ServCfg string `yaml:"serverSettings"`
ServExec string `yaml:"serverExec"`
BackupDir string `yaml:"backupDir"`
UseScreen bool `yaml:"screen"`
ScreenName string `yaml:"screenName"`
} `yaml:"server"`
}
func readCfg(factCfg string) GoConfig {
//read config file (YAML)
fileBytes, err := os.ReadFile(factCfg)
if err != nil {
log.Fatalf("Error reading config file: %v", err)
}
// return Struct
var config GoConfig
err = yaml.Unmarshal(fileBytes, &config)
if err != nil {
log.Fatalf("Error unmarshalling YAML file: %v", err)
}
return config
}
func startStopServer(cmd string, con GoConfig) {
switch cmd {
case "start":
x := fmt.Sprintf("%s --port %d --server-settings %s --start-server %s", con.Config.ServExec, con.Config.ServPort, con.Config.ServCfg, con.Config.WorldFile)
//x := fmt.Sprintf("%s --port %d --server-settings %s --start-server %s; exec sh", con.Config.ServExec, con.Config.ServPort, con.Config.ServCfg, con.Config.WorldFile)
///home/raum/factorio-serverfmt.Println(x)
if con.Config.UseScreen {
fmt.Println("Starting factorio server in screen session")
startScreenCmd := exec.Command("screen", "-dmS", con.Config.ScreenName, "bash", "-c", x, "; exec sh")
err := startScreenCmd.Run()
if err != nil {
log.Fatalf("Failed to start server: %s", err)
} else {
fmt.Printf("Started server on port %d, in screen named %s\n", con.Config.ServPort, con.Config.ScreenName)
}
} else {
startSrvCmd := exec.Command(x)
err := startSrvCmd.Run()
if err != nil {
log.Fatalf("Failed to start server: %s", err)
}
}
case "stop":
quitServerCmd := exec.Command("screen", "-S", con.Config.ScreenName, "-p", "0", "-X", "stuff", "/quit\n")
err := quitServerCmd.Run()
if err != nil {
log.Fatalf("Command failed: %s, Error: %v", quitServerCmd.Args, err)
} else {
fmt.Printf("Server in screen %s stopped\n", con.Config.ScreenName)
}
fmt.Println("Waiting for server to shutdown\r")
//time.Sleep(20 * time.Second)
//fmt.Println("Closing screen session ", con.Config.ScreenName)
//stopScreenCmd := exec.Command("screen", "-S", con.Config.ScreenName, "-p", "0", "-X", "stuff", "exit\n")
//err = stopScreenCmd.Run()
//if err != nil {
// log.Fatalf("Command failed: %s, Error: %v", stopScreenCmd.Args, err)
//} else {
// fmt.Printf("Screen \"%s\" closed\n", con.Config.ScreenName)
//}
}
}
func backUp(cmd string, c GoConfig) {
switch cmd {
case "full":
fmt.Println("Starting full server backup")
t := time.Now()
timeStamp := t.Format(time.RFC3339)
fullBackupName := fmt.Sprintf("%s/ServerBackup.%s.tgz", c.Config.BackupDir, timeStamp)
fullBackup := exec.Command("tar", "-czf", fullBackupName, c.Config.ServDir)
err := fullBackup.Run()
if err != nil {
fmt.Printf("Backup Failed: %s\n", err)
}
case "saves":
fmt.Println("Backing up saves")
t := time.Now()
timeStamp := t.Format(time.RFC3339)
savesBackupName := fmt.Sprintf("%s/SaveBackup.%s.tgz", c.Config.BackupDir, timeStamp)
saveDir := fmt.Sprintf("%s/saves", c.Config.ServDir)
savesBackup := exec.Command("tar", "-czf", savesBackupName, saveDir)
err := savesBackup.Run()
if err != nil {
fmt.Printf("Backup Failed: %s\n", err)
}
}
}
func main() {
c := readCfg(fmConfig)