#!/usr/bin/env bash # Colors default="\e[0m" red="\e[31m" green="\e[32m" yellow="\e[93m" lightblue="\e[94m" blue="\e[34m" magenta="\e[35m" cyan="\e[36m" # Make sure to report and clean up on exit, as these files remain in the container's volume function report() { echo echo -e "${yellow}========================================== error.log ==========================================" find "${HOME}" -name error.log -exec head {} \; -exec tail {} \; -exec rm -f {} \; echo echo -e "${yellow}========================================== script*.log ========================================" find "${HOME}" -name "script*.log" -exec head {} \; -exec tail {} \; -exec rm -f {} \; echo echo -e "${yellow}========================================== *.RPT ==============================================" find "${HOME}" -name "*.RPT" -exec ls -la {} \; -exec tail {} \; -exec rm -f {} \; echo echo -e "${yellow}========================================== End crash log ======================================" } # DayZ Experimental SteamID, because there is no release version of the Linux server yet appid=1042420 # DayZ Release SteamID. This is for mods, as only the release has them. dayz_id=221100 # Command line argument variables # Server config file config=serverDZ.cfg # Server port port=2302 rcon_port=2303 # Server profile directory profile="-profiles=${HOME}/serverprofile/" # To log or not to log. # All possible logging on: #logs="-dologs -adminlog -netlog" # No logs? This should read "-somelogs" logs="-nologs" # Mods. WIP. This will have to come from another file, as the plan is to manage this with # this very script. # mods="@CF;@community-Online-Tools;@Banov;@SimpleAutorun" mods="" # Put them all together dayzparameter=" -config=${config} -port=${port} -mod='${mods}' -freezecheck -fps=60 -BEpath=${HOME}/serverfiles/battleye ${profile} ${logs}" # Base directories CFG_SRC_FILES="/files" SERVER_FILES="${HOME}/serverfiles" SERVER_PROFILE="${HOME}/serverprofile" # Server configuration file SERVER_CFG_FILE="serverDZ.cfg" SERVER_CFG_DST="${SERVER_FILES}/${SERVER_CFG_FILE}" SERVER_CFG_SRC="${CFG_SRC_FILES}/${SERVER_CFG_FILE}" # Used to check if dayZ is installed SERVER_INSTALL_FILE="${SERVER_FILES}/DayZServer" # Steam files STEAM_LOGIN="${HOME}/steamlogin" STEAMCMD=steamcmd # Workshop WORKSHOP_CFG="${HOME}/workshop.cfg" # Other stuff YES="${green}yes${default}" NO="${red}no${default}" fn_usage(){ echo -e " ${red}Bad option or arguments! ${yellow}${*}${default} Usage: ${green}$(basename $0)${yellow} option [ arg1 [ arg2 ] ] Options and arguments: install - Install the DayZ server files login - Login to Steam rcon - Connect to the server using a python RCON client status - Shows the server's status as well as the state of the server files and mods (Needs install, update, etc.) stop - Stop the server update - Update the DayZ server files workshop - Workshop Features activate id [id...] - Activate one or many installed DayZ Workshop item by id add id [id...] - Add one or many DayZ Workshop items by id deactivate id [id...] - Deactivate one or many installed DayZ Workshop items by id - Keeps the addon files but excludes from -mod= list - List Workshop items and their states (Active vs. Non) remove id [id...] - Remove one or many Workshop items by id ${default}" exit 1 } fn_prompt_yn(){ echo -n "${1} (y|N) " >&2 read -s -n 1 a a=$(echo ${a} | tr A-Z a-z) if [[ "${a}" = "y" ]] then echo return 0 else echo return 1 fi } fn_loadconfig_dayz(){ if [ ! -f "${SERVER_INSTALL_FILE}" ] then echo echo -e "The DayZ server files are not installed. Run '${green}docker-compose run --rm main dayzserver install${default}'" echo exit 1 fi # Handle the initial server configuration file if [ ! -f ${SERVER_CFG_DST} ] then echo "Creating initial server configuration file" cp "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}" fi # battleye config and rconpassword setup # The server creates a new file from this file, which it then uses. # Let's make sure to delete it first BE_SERVER_FILE="${HOME}/serverfiles/battleye/beserver_x64.cfg" ALT_BE_SERVER_FILE=$(find ${HOME}/serverfiles/battleye -name "beserver_x64_active*") if [ ! -f "${BE_SERVER_FILE}" ] && [ ! -f "${ALT_BE_SERVER_FILE}" ] then passwd=$(openssl rand -base64 8 | tr -dc 'A-Za-z0-9') if [ "${passwd}" == "" ]; then passwd=$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c10) fi if [ "${passwd}" == "" ]; then printf "[ ${red}FAIL${default} ] Could not generate a passwort for RCON!\nOpen the Battleye config with 'dayzserver rcon'." exit 1 else cat > "${BE_SERVER_FILE}" < ~/py3rcon.config.json } fn_start_dayz(){ # Check for interactive shell if [ -t 0 ] then echo echo -e "Not starting the server in an interactive shell. Start the server using '${green}docker-compose up -d${default}'" echo exit fi # Do the report on exit. Set here so that it only happens once we're starting the server, and not for other actions. trap ' report ' EXIT fn_workshop_mods cd ${SERVER_FILES} # Run the server. Allow docker to restart the container if the script exits with a code other than 0. This is so we can # safely shut the container down without killing the server within. printf "[ ${green}DayZ${default} ] Server starting...\n" ./DayZServer $dayzparameter EXIT_CODE=$? printf "[ ${yellow}DayZ${default} ] Server exited. Exit code: ${EXIT_CODE}\n" exit ${EXIT_CODE} } fn_stop_dayz(){ echo "Stopping DayZ server..." kill -TERM $(pidof DayZServer) } fn_steam_login(){ if [ -f "${STEAM_LOGIN}" ] then if fn_prompt_yn "The steam login is already set. Reset it?" then rm -f "${STEAM_LOGIN}" else echo "Not reset." exit 0 fi fi if [ ! -f "${STEAM_LOGIN}" ] then echo "Setting up Steam credentials" echo -n "Steam Username (anonymous): " read steamlogin if [[ "${steamlogin}" = "" ]] then echo "Steam login set to 'anonymous'" steamlogin="anonymous" fi echo "steamlogin=${steamlogin}" > "${STEAM_LOGIN}" ${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +quit fi } fn_steamlogin_dayz(){ if [ -f "${STEAM_LOGIN}" ] then source "${STEAM_LOGIN}" else echo "No cached Steam credentials. Please configure this now: " fn_steam_login fi } fn_runvalidate_dayz(){ # fn_loadconfig_dayz ${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +app_update "${appid}" validate +quit } fn_install_dayz(){ if [ ! -f "${SERVER_INSTALL_FILE}" ]; then mkdir -p "${SERVER_FILES}" mkdir -p "${SERVER_PROFILE}" printf "[ ${yellow}DayZ${default} ] Downloading DayZ Server-Files!\n" fn_steamlogin_dayz fn_runvalidate_dayz else printf "[ ${lightblue}DayZ${default} ] The Server is already installed.\n" fi } fn_runupdate_dayz(){ if ! diff -q "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}" then echo "=========================================================================" diff -Nau --color "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}" || echo "" echo "=========================================================================" if fn_prompt_yn "The new server configuration file differs from what's installed. Use it?" then echo "Updating the server configuration file" cp "${SERVER_CFG_SRC}" "${SERVER_CFG_DST}" else echo "NOT updating the server configuration file" fi fi ${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" +app_update "${appid}" +quit } fn_update_dayz(){ fn_steamlogin_dayz appmanifestfile=${SERVER_FILES}/steamapps/appmanifest_"${appid}".acf printf "[ ... ] Checking for update:" # gets currentbuild currentbuild=$(grep buildid "${appmanifestfile}" | tr '[:blank:]"' ' ' | tr -s ' ' | cut -d \ -f3) # Removes appinfo.vdf as a fix for not always getting up to date version info from SteamCMD if [ -f "${HOME}/Steam/appcache/appinfo.vdf" ]; then rm -f "${HOME}/Steam/appcache/appinfo.vdf" fi # check for new build availablebuild=$(${STEAMCMD} +login "${steamlogin}" +app_info_update 1 +app_info_print "${appid}" +app_info_print \ "${appid}" +quit | sed -n '/branch/,$p' | grep -m 1 buildid | tr -cd '[:digit:]') if [ -z "${availablebuild}" ]; then printf "\r[ ${red}FAIL${default} ] Checking for update:\n" printf "\r[ ${red}FAIL${default} ] Checking for update:: Not returning version info\n" exit else printf "\r[ ${green}OK${default} ] Checking for update:" fi # compare builds if [ "${currentbuild}" != "${availablebuild}" ]; then printf "\r[ ${green}OK${default} ] Checking for update:: Update available\n" printf "Update available:\n" printf "\tCurrent build: ${red}${currentbuild}${default}\n" printf "\tAvailable build: ${green}${availablebuild}${default}\n" printf "\thttps://steamdb.info/app/${appid}/\n" printf "\nApplying update" # run update fn_runupdate_dayz fn_workshop_mods else printf "\r[ ${green}OK${default} ] Checking for update:: No update available\n" printf "\nNo update available:\n" printf "\tCurrent version: ${green}${currentbuild}${default}\n" printf "\tAvailable version: ${green}${availablebuild}${default}\n" printf "\thttps://steamdb.info/app/${appid}/\n\n" fi } fn_workshop_mods(){ fn_steamlogin_dayz declare -a workshopID workshopfolder="${SERVER_FILES}/steamapps/workshop/content/${dayz_id}" workshoplist="" if [ ! -f "${WORKSHOP_CFG}" ] then echo "No workshop mods..." return else echo "Syncing workshop mods..." fi mapfile -t workshopID < "${WORKSHOP_CFG}" # gather mods for i in "${workshopID[@]}" do if [[ $i =~ ^[0-9] ]] && [ $(expr length $i) -gt 7 ]; then workshoplist+=" +workshop_download_item "${dayz_id}" "$i"" fi done # download mods ${STEAMCMD} +force_install_dir ${SERVER_FILES} +login "${steamlogin}" ${workshoplist} +quit # link mods for i in "${workshopID[@]}" do if [[ $i =~ ^[0-9] ]] && [ $(expr length $i) -gt 7 ] && [ -d "${workshopfolder}/$i" ]; then modname=$(cut -d '"' -f 2 <<< $(grep name ${workshopfolder}/$i/meta.cpp)) if [ ! -d "${SERVER_FILES}/@${modname}" ]; then ln -s ${workshopfolder}/$i "${SERVER_FILES}/@${modname}" &> /dev/null fi find "${workshopfolder}/$i" -depth -exec rename -f 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \; fi done if ls ${SERVER_FILES}/@* 1> /dev/null 2>&1; then printf "\n[ ${green}DayZ${default} ] Copy Key Files from Mods...\n" cp -vu ${SERVER_FILES}/@*/keys/* "${SERVER_FILES}/keys/" > /dev/null 2>&1 fi } fn_rcon(){ exec /usr/local/py3rcon/py3rcon.py --gui ~/py3rcon.config.json } fn_status(){ INSTALLED="${NO}" LOGGED_IN="${NO}" RUNNING="${NO}" MOD_INSTALLED="${yellow}0${default}" MOD_LIST="" # DayZ Server files installation if [ -f "${SERVER_INSTALL_FILE}" ] then INSTALLED="${YES}" fi # Logged into Steam if [ -f "${STEAM_LOGIN}" ] then LOGGED_IN="${YES}" if grep -q anonymous "${STEAM_LOGIN}" then ANONYMOUS="(as anonymous)" fi fi # Running or not if pidof DayZServer > /dev/null then RUNNING="${YES}" fi # Number of mods plus the list denoting on or off echo -e " Status: Logged in to Steam: ${LOGGED_IN} ${ANONYMOUS} Server files installed: ${INSTALLED} Mods installed: ${MOD_INSTALLED}${MOD_LIST} Server running: ${RUNNING} " } case "${1}" in install) fn_loadconfig_dayz fn_install_dayz ;; login) fn_loadconfig_dayz fn_steam_login ;; rcon) fn_rcon "${2}" ;; start) fn_loadconfig_dayz fn_start_dayz ;; status) fn_status ;; stop) fn_stop_dayz ;; update) fn_loadconfig_dayz fn_update_dayz ;; workshop) fn_loadconfig_dayz fn_workshop_mods "${2}" ;; **) fn_usage "$*" ;; esac