From c219a6bf29a55a9590f77f337265adc2872dc952 Mon Sep 17 00:00:00 2001 From: Michael <12646562+mbround18@users.noreply.github.com> Date: Sat, 6 Feb 2021 20:33:53 -0700 Subject: [PATCH] Mbround18 #8 auto update (#9) * Auto Update Functions and clean up * Fixed redundant start captures and fixed arguments * Fixed output messages --- Cargo.lock | 159 +++++++++++++++++++++++++ Cargo.toml | 1 + Dockerfile | 36 ++++-- docker-compose.yml | 5 +- src/commands/install.rs | 14 +-- src/commands/start.rs | 96 ++++----------- src/commands/stop.rs | 22 +++- src/cron/auto-update | 1 + src/executable.rs | 17 +-- src/files/mod.rs | 77 ++++++++++++ src/files/server_exit.rs | 18 +++ src/files/server_pid.rs | 30 +++++ src/files/start_server_rusty.rs | 62 ++++++++++ src/main.rs | 5 +- src/scripts/auto_update.sh | 10 ++ {scripts => src/scripts}/entrypoint.sh | 13 +- src/steamcmd.rs | 8 +- 17 files changed, 456 insertions(+), 118 deletions(-) create mode 100644 src/cron/auto-update create mode 100644 src/files/mod.rs create mode 100644 src/files/server_exit.rs create mode 100644 src/files/server_pid.rs create mode 100644 src/files/start_server_rusty.rs create mode 100644 src/scripts/auto_update.sh rename {scripts => src/scripts}/entrypoint.sh (76%) diff --git a/Cargo.lock b/Cargo.lock index ac0d72cf..ff5135b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "cc" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" + [[package]] name = "cfg-if" version = "1.0.0" @@ -78,6 +84,64 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "const_fn" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" +dependencies = [ + "cfg-if", + "const_fn", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + [[package]] name = "dialoguer" version = "0.7.1" @@ -90,6 +154,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "encode_unicode" version = "0.3.6" @@ -174,6 +250,34 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "odin" version = "1.1.0" @@ -183,10 +287,17 @@ dependencies = [ "log", "pad", "serde", + "sysinfo", "tinytemplate", "which", ] +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" + [[package]] name = "os_str_bytes" version = "2.4.0" @@ -290,6 +401,31 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rayon" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.4" @@ -329,6 +465,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.123" @@ -377,6 +519,23 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "sysinfo" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c14e2f7068e99d8d3e3580787ffc6c7d21ad90393ff5e54523435197ccb43e6" +dependencies = [ + "cc", + "cfg-if", + "core-foundation-sys", + "doc-comment", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "tempfile" version = "3.2.0" diff --git a/Cargo.toml b/Cargo.toml index 824327d6..aa417e3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ which = "4.0.2" dialoguer = "0.7.1" tinytemplate = "1.1" serde = { version = "1.0", features = ["derive"] } +sysinfo = "0.16.1" [profile.dev] opt-level = 0 diff --git a/Dockerfile b/Dockerfile index 305dc9a9..cdecd09c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN cargo install --path . \ FROM registry.hub.docker.com/library/alpine:latest as ScriptSanitize WORKDIR /data/scripts -COPY ./scripts/* . +COPY src/scripts/* ./ RUN apk add dos2unix --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted \ && dos2unix /data/scripts/** @@ -27,20 +27,42 @@ RUN apk add dos2unix --update-cache --repository http://dl-3.alpinelinux.org/al # --------------- # FROM registry.hub.docker.com/cm2network/steamcmd:root -RUN apt-get update \ - && apt-get install -y htop net-tools nano netcat curl wget +RUN apt-get update \ + && apt-get install -y \ + htop net-tools nano \ + netcat curl wget \ + cron -USER steam +# Set up timezone information +ENV TZ=America/Los_Angeles +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -RUN mkdir -p /home/steam/valheim \ - && mkdir -p /home/steam/scripts +# Copy hello-cron file to the cron.d directory +COPY --chown=steam:steam src/cron/auto-update /etc/cron.d/auto-update + +# Give execution rights on the cron job +RUN chmod 0644 /etc/cron.d/auto-update + +# Apply cron job +RUN crontab /etc/cron.d/auto-update + +# Setup Directories +RUN usermod -d /home/steam steam \ + && mkdir -p /home/steam/valheim \ + && chown -R steam:steam /home/steam/valheim \ + && mkdir -p /home/steam/scripts \ + && chown -R steam:steam /home/steam/scripts + +# Switch to steam user. +USER steam ENV NAME "Valheim Docker" ENV WORLD "Dedicated" ENV PORT "2456" ENV PASSWORD "" +ENV AUTO_UPDATE "0" -COPY --from=ScriptSanitize --chown=steam:steam /data/scripts/entrypoint.sh /home/steam/scripts/ +COPY --from=ScriptSanitize --chown=steam:steam /data/scripts/*.sh /home/steam/scripts/ COPY --from=RustBuilder --chown=steam:steam /data/odin/target/release /home/steam/odin RUN mkdir -p /home/steam/valheim \ diff --git a/docker-compose.yml b/docker-compose.yml index 54b774d4..79e46061 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,4 @@ +version: "3" services: valheim: image: mbround18/valheim:latest @@ -13,5 +14,5 @@ services: - "2457:2457/udp" - "2458:2458/udp" volumes: - - ./tmp/valheim/saves:/home/steam/.config/unity3d/IronGate/Valheim - - ./tmp/valheim/server:/home/steam/valheim + - ./tmp/saves:/home/steam/.config/unity3d/IronGate/Valheim + - ./tmp/server:/home/steam/valheim diff --git a/src/commands/install.rs b/src/commands/install.rs index 072f3ca0..2f04d9e4 100644 --- a/src/commands/install.rs +++ b/src/commands/install.rs @@ -1,19 +1,19 @@ use crate::steamcmd::steamcmd_command; -use crate::executable::{execute_mut, handle_exit_status}; -use std::process::Stdio; +use crate::executable::{execute_mut}; +use std::process::{Stdio, ExitStatus}; use crate::utils::{get_working_dir}; +use log::{info}; -pub fn invoke(app_id: i64) { - println!("Installing {} to {}", app_id, get_working_dir()); +pub fn invoke(app_id: i64) -> std::io::Result { + info!("Installing {} to {}", app_id, get_working_dir()); let login = "+login anonymous".to_string(); let force_install_dir = format!("+force_install_dir {}", get_working_dir()).to_string(); let app_update = format!("+app_update {}", app_id); - let mut steamcmd = steamcmd_command(); + let mut steamcmd = steamcmd_command(); let install_command = steamcmd .args(&[login, force_install_dir, app_update]) .arg("+quit") .stdout(Stdio::inherit()) .stderr(Stdio::inherit()); - let result = execute_mut(install_command); - handle_exit_status(result, "Successfully installed Valheim!".to_string()) + execute_mut(install_command) } diff --git a/src/commands/start.rs b/src/commands/start.rs index 31317ad1..61f66e1d 100644 --- a/src/commands/start.rs +++ b/src/commands/start.rs @@ -2,84 +2,25 @@ use crate::executable::{create_execution}; use std::process::{Stdio}; use clap::{ArgMatches}; use crate::utils::{get_variable, server_installed, get_working_dir}; -use std::fs::{File, remove_file}; -use std::io::Write; -use log::{info, error, debug}; -use tinytemplate::TinyTemplate; -use serde::Serialize; - -#[derive(Serialize)] -struct Context { - command: String, - arguments: String -} - -static TEMPLATE: &'static &str = &r#" -#!/usr/bin/env bash -cd "$(dirname "$0")" -# This script will be overwritten at each start! - -{command} {arguments} 2>&1 | tee ./output.log & -disown - -"#; - -fn parse_to_script(context: Context) -> String{ - let mut tt = TinyTemplate::new(); - tt.add_template( - "hello", &TEMPLATE).unwrap(); - tt.render("hello", &context).unwrap().replace(""", "\"") -} - -fn create_start_server_script(command: String, arguments: String, dry_run: bool) { - let context = Context { - command, - arguments - }; - let source = parse_to_script(context); - if dry_run { - info!("This would have written a file to ./start_server_rusty.sh with content: \n {}", source); - } else { - match File::create("./start_server_rusty.sh") { - Ok(mut file) => { - match file.write_all(source.as_bytes()) { - Ok(_) => println!("Successfully written script file."), - _ => println!("Failed to write script file.") - }; - match create_execution("chmod").args(&["+x", "./start_server_rusty.sh"]).output() { - Ok(_) => info!("Success changing permission"), - _ => error!("Unable to change permissions") - }; - } - _ => error!("Failed to write script file.") - }; - } -} - -fn parse_arg(args: &ArgMatches, name: &str, default: &str) -> String { - format!("-{} \"{}\"", name, get_variable(args, name,default.to_string())) -} +use log::{info, error}; +use crate::files::start_server_rusty::{write_rusty_start_script, ValheimArguments}; +use crate::files::server_exit; pub fn invoke(args: &ArgMatches) { - let paths = &[get_working_dir(), "server_exit.drp".to_string()]; - let server_exit = &paths.join("/"); - match remove_file(server_exit) { - Ok(_) => info!("Deleted server exit file."), - Err(_) => { - debug!("Server exit file did no pre-exist. Good!") - } - }; - + server_exit::delete_if_exist(); + info!("Setting up start scripts..."); let mut command = create_execution("bash"); - let command_args: &str = &[ - parse_arg(args, "port", "2456"), - parse_arg(args, "name", "Valheim Docker"), - parse_arg(args, "world", "Dedicated"), - parse_arg(args, "password", "12345"), - ].join(" "); - let dry_run: bool = args.is_present("dry_run"); let server_executable = &[get_working_dir(), "valheim_server.x86_64".to_string()].join("/"); - create_start_server_script(server_executable.to_string(), command_args.to_string(), dry_run); + let script_args = &ValheimArguments { + port: get_variable(args, "port", "2456".to_string()).to_string(), + name: get_variable(args, "name", "Valheim powered by Odin".to_string()), + world: get_variable(args, "world", "Dedicated".to_string()), + password: get_variable(args, "password", "12345".to_string()), + command: server_executable.to_string() + }; + let dry_run: bool = args.is_present("dry_run"); + info!("Looking for burial mounds..."); + write_rusty_start_script(script_args, dry_run); if !dry_run { if server_installed() { let updated_command = command @@ -89,7 +30,12 @@ pub fn invoke(args: &ArgMatches) { .arg("./start_server_rusty.sh") .env("LD_LIBRARY_PATH", "${PWD}/linux64:${LD_LIBRARY_PATH}"); match updated_command.output() { - Ok(output) => print!("Exit with code {}", output.status), + Ok(output) => { + info!("Exit with code {}", output.status); + info!("Server has started..."); + info!("Check out ./output.log for the logs."); + info!("Keep an eye out for \"Game server connected\" and you server should be live!"); + }, _ => { error!("An error has occurred!") } diff --git a/src/commands/stop.rs b/src/commands/stop.rs index 7ae2cd6f..624c4e91 100644 --- a/src/commands/stop.rs +++ b/src/commands/stop.rs @@ -1,8 +1,10 @@ use crate::utils::{get_working_dir, server_installed}; -use log::{info, error}; +use log::{info, error, debug}; use clap::ArgMatches; -use std::fs::{File}; -use std::io::Write; +use crate::files::server_pid::is_running; +use std::thread::sleep; +use std::time::Duration; +use crate::files::server_exit::stop_server; pub fn invoke(args: &ArgMatches) { let paths = &[get_working_dir(), "server_exit.drp".to_string()]; @@ -17,8 +19,16 @@ pub fn invoke(args: &ArgMatches) { error!("Failed to find server executable!"); return; } - let mut file = File::create(script_path).unwrap(); - file.write_all(b"1").unwrap(); - info!("Stop file created, Check logs, server should be stopping."); + stop_server(); + info!("Server Stop triggered! Waiting for server to stop."); + loop { + if is_running() { + debug!("Server is still running..."); + sleep(Duration::from_secs(2)); + } else { + info!("Server has been stopped!"); + break; + } + } } } diff --git a/src/cron/auto-update b/src/cron/auto-update new file mode 100644 index 00000000..b9820a6a --- /dev/null +++ b/src/cron/auto-update @@ -0,0 +1 @@ +0 1 * * * steam bash /home/steam/scripts/auto_update.sh diff --git a/src/executable.rs b/src/executable.rs index 27e334bb..1f957040 100644 --- a/src/executable.rs +++ b/src/executable.rs @@ -1,11 +1,12 @@ use std::process::{Command, exit, ExitStatus}; use std::path::Path; +use log::{info, error}; pub fn find_command(executable: &str) -> Option { let script_file = Path::new(executable); if script_file.exists() { - println!("Executing: {} .....", executable.to_string()); + info!("Executing: {} .....", executable.to_string()); Option::from(Command::new(executable.to_string())) } else { match which::which(executable) { @@ -13,7 +14,7 @@ pub fn find_command(executable: &str) -> Option { Option::from(Command::new(executable_path)) }, Err(_e) => { - eprint!("Failed to find {}", executable); + error!("Failed to find {} in path", executable); None } } @@ -24,7 +25,7 @@ pub fn create_execution(executable: &str) -> Command { match find_command(executable) { Some(command) => command, None => { - eprint!("Unable to launch command {}", executable); + error!("Unable to launch command {}", executable); exit(1) } } @@ -34,7 +35,7 @@ pub fn execute_mut(command: &mut Command) -> std::io::Result { match command.spawn() { Ok(mut subprocess) => subprocess.wait(), _ => { - println!("Failed to run process!"); + error!("Failed to run process!"); exit(1) } } @@ -44,16 +45,16 @@ pub fn handle_exit_status(result: std::io::Result, success_message: match result { Ok(exit_status) => { if exit_status.success() { - println!("{}", success_message); + info!("{}", success_message); } else { match exit_status.code() { - Some(code) => println!("Exited with status code: {}", code), - None => println!("Process terminated by signal") + Some(code) => info!("Exited with status code: {}", code), + None => info!("Process terminated by signal") } } } _ => { - eprint!("An error has occurred and the command returned no exit code!"); + error!("An error has occurred and the command returned no exit code!"); exit(1) } } diff --git a/src/files/mod.rs b/src/files/mod.rs new file mode 100644 index 00000000..b98e70d5 --- /dev/null +++ b/src/files/mod.rs @@ -0,0 +1,77 @@ +pub mod start_server_rusty; +pub mod server_exit; +pub mod server_pid; + +use crate::utils::get_working_dir; +use std::path::Path; +use std::fs::{remove_file, File}; +use crate::executable::create_execution; +use std::io::Write; +use log::{info,error}; +use std::fs; + +pub trait FileManager { + fn path(&self) -> String; + fn exists(&self) -> bool { + Path::new(self.path().as_str()).exists() + } + fn remove(&self) -> bool { + match remove_file(self.path()) { + Ok(_) => { + info!("Successfully deleted {}", self.path()); + true + }, + Err(_) => { + error!("Did not find or could not delete {}", self.path()); + false + } + } + } + fn read(&self) -> String { + if self.exists() { + fs::read_to_string(self.path()).unwrap() + } else { + "".to_string() + } + } + fn write(&self, content: String) -> bool { + match File::create(self.path()) { + Ok(mut file) => { + match file.write_all(content.as_bytes()) { + Ok(_) => { + info!("Successfully written {}", self.path()); + true + }, + _ => { + error!("Failed to write {}", self.path()); + false + } + } + } + _ => { + error!("Failed to write {}", self.path()); + false + } + } + } + fn set_executable(&self) -> bool { + if let Ok(_output) = create_execution("chmod").args(&["+x", self.path().as_str()]).output() { + info!("Successfully set {} to executable", self.path()); + true + } + else { + error!("Unable to set {} to executable", self.path()); + false + } + } +} + +pub struct ManagedFile { + pub(crate) name: &'static str +} + +impl FileManager for ManagedFile { + fn path(&self) -> String{ + format!("{}/{}", get_working_dir(), self.name) + } +} diff --git a/src/files/server_exit.rs b/src/files/server_exit.rs new file mode 100644 index 00000000..96bd8ef5 --- /dev/null +++ b/src/files/server_exit.rs @@ -0,0 +1,18 @@ +use crate::files::{ManagedFile, FileManager}; +use log::{info}; + +const SERVER_EXIT: ManagedFile = ManagedFile { + name: "server_exit.drp" +}; + +pub fn delete_if_exist() { + if SERVER_EXIT.exists() { + SERVER_EXIT.remove(); + } +} + +pub fn stop_server() { + if SERVER_EXIT.write("1".to_string()) { + info!("Created Server Stop Waiting for it to finish."); + }; +} diff --git a/src/files/server_pid.rs b/src/files/server_pid.rs new file mode 100644 index 00000000..139c2344 --- /dev/null +++ b/src/files/server_pid.rs @@ -0,0 +1,30 @@ +use crate::files::{ManagedFile, FileManager}; +use sysinfo::{System, ProcessExt}; +use sysinfo::SystemExt; + +const SERVER_PID: ManagedFile = ManagedFile { + name: "valheim_server.pid" +}; + +pub fn read_pid() -> String { + SERVER_PID.read() +} + +pub fn is_running() -> bool { + let pid: String = read_pid(); + if pid.len() > 0 { + let processed_pid: i32 = pid.parse().unwrap_or(0); + return if processed_pid != 0 { + let system = System::new(); + let process = system.get_process(processed_pid); + return if let Some(running_process) = process { + running_process.pid() == processed_pid + } else { + false + } + } else { + false + } + } + false +} diff --git a/src/files/start_server_rusty.rs b/src/files/start_server_rusty.rs new file mode 100644 index 00000000..b3b4bbea --- /dev/null +++ b/src/files/start_server_rusty.rs @@ -0,0 +1,62 @@ +use crate::files::{FileManager, ManagedFile}; +use tinytemplate::TinyTemplate; +use serde::Serialize; +use log::{info, error}; +use std::process::exit; + +static TEMPLATE: &'static &str = &r#" +#!/usr/bin/env bash +cd "$(dirname "$0")" +# This script will be overwritten at each start! + +# Launch Command +{command} \ + -port {port} \ + -name "{name}" \ + -world "{world}" \ + -world "{world}" \ + -password "{password}" \ + -public 1 \ + 2>&1 | tee ./output.log > /dev/null 2>&1 & + +# Capture the PID +echo $! > ./valheim_server.pid +# Release the process +disown + +"#; + +#[derive(Serialize)] +pub struct ValheimArguments { + pub(crate) port: String, + pub(crate) name: String, + pub(crate) world: String, + pub(crate) password: String, + pub(crate) command: String +} + +pub fn write_rusty_start_script(context: &ValheimArguments, dry_run: bool) { + let mut tt = TinyTemplate::new(); + tt.add_template( + "hello", &TEMPLATE).unwrap(); + let content = tt.render("hello", &context).unwrap().replace(""", "\""); + let file = ManagedFile { + name: "start_server_rusty.sh" + }; + + if dry_run { + info!("This would have written a file to\n{}", file.path()); + info!("With contents of:\n{}", content); + } else { + if file.write(content) { + info!("Created the {} script successfully!", file.path()); + if file.set_executable() { + info!("Successfully set {} to executable!", file.path()); + return; + }; + } else { + error!("Failed to create file!"); + exit(1); + }; + } +} diff --git a/src/main.rs b/src/main.rs index 4bd89c99..7e1bae0c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,10 +3,12 @@ mod commands; mod executable; mod utils; mod logger; +mod files; use clap::{App, load_yaml}; use log::{SetLoggerError, LevelFilter, debug}; use crate::logger::OdinLogger; +use crate::executable::handle_exit_status; static LOGGER: OdinLogger = OdinLogger; static GAME_ID: i64 = 896660; @@ -31,7 +33,8 @@ fn main() { setup_logger(matches.is_present("debug")).unwrap(); if let Some(ref _match) = matches.subcommand_matches("install") { - commands::install::invoke(GAME_ID); + let result = commands::install::invoke(GAME_ID); + handle_exit_status(result, "Successfully installed Valheim!".to_string()) }; if let Some(ref start_matches) = matches.subcommand_matches("start") { diff --git a/src/scripts/auto_update.sh b/src/scripts/auto_update.sh new file mode 100644 index 00000000..cc44a8ce --- /dev/null +++ b/src/scripts/auto_update.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +cd "$(dirname "$0")" || exit 1 + +if [[ "${AUTO_UPDATE}" = "1" ]]; then + cd /home/steam/valhaim || exit 1 + odin install + odin stop + sleep 60 + odin start +fi diff --git a/scripts/entrypoint.sh b/src/scripts/entrypoint.sh similarity index 76% rename from scripts/entrypoint.sh rename to src/scripts/entrypoint.sh index b3a35ac5..fc5fc437 100644 --- a/scripts/entrypoint.sh +++ b/src/scripts/entrypoint.sh @@ -18,18 +18,11 @@ export PATH="/home/steam/odin:$PATH" # Setting up server -if [ -f "/home/steam/valheim/valheim_server.x86_64" ]; then - log "Server installed!" -else - log "Installing Server..." - odin install -fi +odin install log "Herding Cats..." -odin start & - -#export LD_LIBRARY_PATH=${TEMP_LD_LIBRARY_PATH} +odin start cleanup() { log "Halting server! Received interrupt!" @@ -39,6 +32,8 @@ cleanup() { trap cleanup INT TERM EXIT +tail -f /home/steam/valheim/output.log + while :; do sleep 1s done diff --git a/src/steamcmd.rs b/src/steamcmd.rs index bd6ff0f1..28970fad 100644 --- a/src/steamcmd.rs +++ b/src/steamcmd.rs @@ -1,21 +1,23 @@ use std::process::{Command, exit}; +use log::{info, error}; use crate::executable::{find_command}; const STEAMCMD_EXE: &str = "/home/steam/steamcmd/steamcmd.sh"; pub fn steamcmd_command() -> Command { match find_command("steamcmd") { Some(steamcmd) => { - println!("steamcmd found in path"); + info!("steamcmd found in path"); steamcmd }, None => { + error!("Checking for script under steam user."); match find_command(STEAMCMD_EXE) { Some(steamcmd) => { - println!("Using steamcmd script at {}", STEAMCMD_EXE); + info!("Using steamcmd script at {}", STEAMCMD_EXE); steamcmd }, None => { - eprint!("SteamCMD Executable Not Found! Please install steamcmd... https://developer.valvesoftware.com/wiki/SteamCMD"); + error!("\nSteamCMD Executable Not Found! \nPlease install steamcmd... \nhttps://developer.valvesoftware.com/wiki/SteamCMD\n"); exit(1); } }