source: scripts/usr/local/lib/7dtd/common.sh@ 489

Last change on this file since 489 was 481, checked in by alloc, 13 months ago

Scripts

File size: 10.0 KB
RevLine 
[17]1#!/bin/bash
2
[258]3# Copyright 2016 Christian 'Alloc' Illy
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17
[17]18# Provides common functions for 7dtd-scripts. Not intended to be run directly.
19
20# Check if the script is run as root (exit otherwise) and load global config
21checkRootLoadConf() {
22 if [ `id -u` -ne 0 ]; then
23 echo "This script has to be run as root!"
24 exit 10
25 fi
26 . /etc/7dtd.conf
27}
28
29# Get the config path for the given instance
30# Params:
31# 1: Instance name
32# Returns:
33# Config path for instance
34getInstancePath() {
35 echo $SDTD_BASE/instances/$1
36}
37
[19]38# Check if the given instance name is valid (no blanks, no special chars,
39# only letters, digits, underscore, hyphen -> [A-Za-z0-9_\-])
40# Params:
41# 1: Instance name
42# Returns:
43# 0/1 instance not valid/valid
44isValidInstanceName() {
45 if [[ "$1" =~ ^[A-Za-z0-9_\-]+$ ]]; then
46 echo 1
47 else
48 echo 0
49 fi
50}
51
[17]52# Check if the given instance name is an existing instance
53# Params:
54# 1: Instance name
55# Returns:
56# 0/1 instance not valid/valid
57isValidInstance() {
[19]58 if [ ! -z "$1" ]; then
59 if [ $(isValidInstanceName "$1") -eq 1 ]; then
60 if [ -d $(getInstancePath "$1") ]; then
61 if [ -f $(getInstancePath "$1")/config.xml ]; then
62 echo 1
63 return
64 fi
[17]65 fi
66 fi
67 fi
[19]68 echo 0
[17]69}
70
71# Check if the given instance is currently running
72# Params:
73# 1: Instance name
74# Returns:
75# 0 = not running
76# 1 = running
77isRunning() {
[25]78 $SSD --status --pidfile $(getInstancePath $1)/7dtd.pid
[17]79 if [ $? -eq 0 ]; then
80 echo 1
81 else
82 echo 0
83 fi
84}
85
86# Get list of defined instances
87# Returns:
88# List of instances
89getInstanceList() {
[19]90 local IF
[17]91 for IF in $SDTD_BASE/instances/*; do
[19]92 local I=`basename $IF`
[17]93 if [ $(isValidInstance $I) -eq 1 ]; then
94 echo $I
95 fi
96 done
97}
98
99# Get the PID of the instance if it is running, 0 otherwise
100# Params:
101# 1: Instance name
102# Returns:
103# 0 if not running
104# PID otherwise
105getInstancePID() {
106 if [ $(isRunning $1) -eq 1 ]; then
107 cat $(getInstancePath $1)/7dtd.pid
108 else
109 echo 0
110 fi
111}
112
[308]113# Get the installed branch name
114# Returns:
115# "public" if no engine installed or no appmanifest found or buildid could not be read
116# Branch name
117getLocalBranch() {
118 local LOCAL="public"
[478]119 if [ -d "$SDTD_BASE/engine" ]; then
120 local APPMANIFEST=$(find $SDTD_BASE/engine -type f -name "appmanifest_294420.acf")
121 if [ -f "$APPMANIFEST" ]; then
[481]122 LOCAL=$(grep -i '"betakey"' "$APPMANIFEST" | tr '[:blank:]"' ' ' | tr -s ' ' | cut -d\ -f3)
[478]123 if [[ -z $LOCAL ]]; then
124 LOCAL="public"
125 else
126 echo $LOCAL
127 return
128 fi
[308]129 fi
130 fi
131 echo $LOCAL
132}
133
[53]134# Get the local engine version number (i.e. build id)
135# Returns:
136# 0 if no engine installed or no appmanifest found or buildid could not be read
137# Build Id otherwise
138getLocalEngineVersion() {
139 local LOCAL=0
[478]140 if [ -d "$SDTD_BASE/engine" ]; then
141 local APPMANIFEST=$(find $SDTD_BASE/engine -type f -name "appmanifest_294420.acf")
142 if [ -f "$APPMANIFEST" ]; then
[481]143 LOCAL=$(grep -i '"buildid"' "$APPMANIFEST" | tr '[:blank:]"' ' ' | tr -s ' ' | cut -d\ -f3)
[478]144 if [ $(isANumber "$LOCAL") -eq 0 ]; then
145 LOCAL=0
146 fi
[53]147 fi
148 fi
149 echo $LOCAL
150}
151
[308]152# Get the local engine update time
[53]153# Returns:
[308]154# 0 if no engine installed or no appmanifest found or buildid could not be read
155# Update time otherwise
156getLocalEngineUpdateTime() {
157 local LOCAL=0
[478]158 if [ -d "$SDTD_BASE/engine" ]; then
159 local APPMANIFEST=$(find $SDTD_BASE/engine -type f -name "appmanifest_294420.acf")
160 if [ -f "$APPMANIFEST" ]; then
[481]161 LOCAL=$(grep -i '"LastUpdated"' "$APPMANIFEST" | tr '[:blank:]"' ' ' | tr -s ' ' | cut -d\ -f3)
[478]162 if [ $(isANumber "$LOCAL") -eq 0 ]; then
163 LOCAL=0
164 else
165 date --date="@${LOCAL}" "+%Y-%m-%d %H:%M:%S"
166 return
167 fi
[308]168 fi
[53]169 fi
[308]170 echo $LOCAL
[53]171}
172
[478]173
174# Get the latest remote (on Steam) engine version numbers etc
175updateRemoteEngineInfo() {
176 local DOCHECK=no
177 if [ ! -e /tmp/7dtd-appinfo ]; then
178 DOCHECK=yes
179 else
180 AGE=$((`date +%s` - `stat -L --format %Y /tmp/7dtd-appinfo`))
181 if [ $AGE -gt 300 ]; then
182 DOCHECK=yes
183 fi
184 fi
185 if [ "$DOCHECK" = "yes" ]; then
186 echo "Updating version information..."
[479]187 rm -f /root/Steam/appcache/appinfo.vdf
[478]188 cd $SDTD_BASE/steamcmd
189
190 expect /usr/local/lib/7dtd/steamcmd.exp $SDTD_BASE/steamcmd/steamcmd.sh 294420 2>/dev/null > /tmp/7dtd-appinfo
191
[479]192 local BUILDID=$(getRemoteBuildId public)
[478]193
194 if [ $(isANumber "$BUILDID") -eq 0 ]; then
195 rm -f /tmp/7dtd-appinfo
196 fi
197 fi
198}
199
200# Get the latest build id (on Steam)
201# Params:
202# 1. Branch name
203# Returns:
204# "?" if data could not be retrieved
205# BuildId otherwise
206getRemoteBuildId() {
[479]207 if [ ! -f "/tmp/7dtd-appinfo" ]; then
208 echo "?"
209 return
210 fi
211
[478]212 local BUILDID=$(grep -A 1000 \"branches\" /tmp/7dtd-appinfo | grep -A 1000 \"$1\" | grep -B 10 \} --max-count=1 | grep \"buildid\" | cut -d\" -f4)
213
214 if [ $(isANumber "$BUILDID") -eq 0 ]; then
215 echo "?"
216 else
217 echo $BUILDID
218 fi
219}
220
221# Get the update time of the latest build (on Steam)
222# Params:
223# 1. Branch name
224# Returns:
225# "?" if data could not be retrieved
226# Update timestamp otherwise
227getRemoteBuildUpdateTime() {
[479]228 if [ ! -f "/tmp/7dtd-appinfo" ]; then
229 echo "?"
230 return
231 fi
232
[478]233 local TIMESTAMP=$(grep -A 1000 \"branches\" /tmp/7dtd-appinfo | grep -A 1000 \"$1\" | grep -B 10 \} --max-count=1 | grep \"timeupdated\" | cut -d\" -f4)
234
235 if [ $(isANumber "$TIMESTAMP") -eq 0 ]; then
236 echo "?"
237 else
238 date --date="@${TIMESTAMP}" "+%Y-%m-%d %H:%M:%S"
239 fi
240}
241
242# Get a list of available branch names, blank separated
243# Returns:
244# Blank separated list of branch names (can be empty if an error occured)
245getBranchNames() {
[479]246 if [ ! -f "/tmp/7dtd-appinfo" ]; then
247 return
248 fi
249
[478]250 grep -A 1000 \"branches\" /tmp/7dtd-appinfo | grep -E '^[[:space:]]*"[^"]+"[[:space:]]*$' | tail --lines=+2 | cut -d\" -f2
251}
252
[17]253# Check if a given port range (baseport, baseport+1, baseport+2 each udp)
[19]254# is already in use by any other instance
[17]255# Params:
256# 1: Baseport
[19]257# 2: Current instance (ignored)
[17]258# Returns:
259# 0/1 not in use/in use
260checkGamePortUsed() {
[19]261 local PORTMIN=$1
262 local PORTMAX=$(( $1 + 2 ))
263 local I
[17]264 for I in $(getInstanceList); do
[19]265 if [ "$2" != "$I" ]; then
266 local CURPORTMIN=$(getConfigValue $I "ServerPort")
267 local CURPORTMAX=$(( $CURPORTMIN + 2 ))
268 if [ $PORTMAX -ge $CURPORTMIN -a $PORTMIN -le $CURPORTMAX ]; then
269 echo 1
270 return
271 fi
[17]272 fi
273 done
274 echo 0
275}
276
[19]277# Check if a given TCP port is already in use by any instance (either by control
278# panel or telnet)
[17]279# Params:
280# 1: Port
281# Returns:
282# 0/1 not in use/in use
[19]283checkTCPPortUsed() {
284 local I
[17]285 for I in $(getInstanceList); do
[19]286 if [ "$2" != "$I" ]; then
287 local CURENABLED=$(getConfigValue $I "TelnetEnabled")
288 local CURPORT=$(getConfigValue $I "TelnetPort")
289 if [ "$CURENABLED" = "true" -a $CURPORT -eq $1 ]; then
290 echo 1
291 return
292 fi
293 CURENABLED=$(getConfigValue $I "ControlPanelEnabled")
294 CURPORT=$(getConfigValue $I "ControlPanelPort")
295 if [ "$CURENABLED" = "true" -a $CURPORT -eq $1 ]; then
296 echo 1
297 return
298 fi
[17]299 fi
300 done
301 echo 0
302}
303
304# Send a single command to the telnet port
305# Params:
306# 1: Instance name
307# 2: Command
[46]308# 3: (Optional) Timeout in sec, defaulting to 1
[17]309# Returns:
310# String of telnet output
311telnetCommand() {
[19]312 local TEL_ENABLED=$(getConfigValue $1 TelnetEnabled)
313 local TEL_PORT=$(getConfigValue $1 TelnetPort)
314 local TEL_PASS=$(getConfigValue $1 TelnetPassword)
[88]315 if [ "$TEL_ENABLED" = "true" ]; then
[46]316 local TEMPFILE=$(mktemp)
317 rm -f $TEMPFILE
318 mkfifo $TEMPFILE
319 exec 3<> $TEMPFILE
320 nc 127.0.0.1 $TEL_PORT <&3 &
321 local NCPID=$!
[304]322 disown
[88]323 if [ -n "$TEL_PASS" ]; then
324 printf "$TEL_PASS\n$2\n" >&3
325 else
326 printf "$2\n" >&3
327 fi
[46]328 sleep ${3:-1}
329 printf "exit\n" >&3
330 sleep 0.2
331 kill -9 $NCPID > /dev/null 2>&1
332 exec 3>&-
333 rm -f $TEMPFILE
[17]334 else
[88]335 echo "Telnet not enabled."
[17]336 fi
337}
338
339# Get all hook files for the given hook-name
340# Params:
341# 1: Hook name
[259]342# 2: Instance name
[17]343# Returns:
344# Names of hook files
345getHooksFor() {
[308]346 if [ -n "$2" ]; then
[260]347 if [ -d $(getInstancePath $2)/hooks/$1 ]; then
[259]348 local H
[260]349 for H in $(getInstancePath $2)/hooks/$1/*.sh; do
[259]350 echo "$H"
351 done
352 fi
353 fi
[17]354 if [ -d $SDTD_BASE/hooks/$1 ]; then
[19]355 local H
[17]356 for H in $SDTD_BASE/hooks/$1/*.sh; do
357 echo "$H"
358 done
359 fi
360}
361
362# Lowercase passed string
363# Params:
364# 1: String
365# Returns:
366# Lowercased string
367lowercase() {
368 echo "${1}" | tr "[:upper:]" "[:lower:]"
369}
370
371# Prepare passed string as part of camelcase, i.e. first char upper case, others
372# lowercase
373# Params:
374# 1: String
375# Returns:
376# Transformed string
377camelcasePrep() {
378 echo $(echo "${1:0:1}" | tr "[:lower:]" "[:upper:]")$(echo "${1:1}" | tr "[:upper:]" "[:lower:]")
379}
380
[19]381# Check if given value is a (integer) number
382# Params:
383# 1: Value
384# Returns:
385# 0/1 for NaN / is a number
386isANumber() {
387 if [[ $1 =~ ^[0-9]+$ ]] ; then
388 echo "1"
389 else
390 echo "0"
391 fi
392}
393
394# Check if given value is a boolean (true/false, yes/no, y/n)
395# Params:
396# 1: Value
397# Returns:
398# 0/1
399isABool() {
400 local LOW=$(lowercase "$1")
401 if [ "$LOW" = "false" -o "$LOW" = "true"\
402 -o "$LOW" = "yes" -o "$LOW" = "y"\
403 -o "$LOW" = "no" -o "$LOW" = "n" ]; then
404 echo 1
405 else
406 echo 0
407 fi
408}
409
410# Convert the given value to a boolean 0/1
411# Params:
412# 1: Value
413# Returns:
414# 0/1 as false/true
415getBool() {
416 if [ $(isABool "$1") -eq 0 ]; then
417 echo 0
418 else
419 local LOW=$(lowercase "$1")
420 if [ "$LOW" = "true" -o "$LOW" = "yes" -o "$LOW" = "y" ]; then
421 echo 1
422 else
423 echo 0
424 fi
425 fi
426}
427
[17]428listCommands() {
[19]429 local C
[17]430 for C in $(declare -F | cut -d\ -f3 | grep "^sdtdCommand"\
431 | grep -v "Help$"\
432 | grep -v "Description$"\
433 | grep -v "Expects$"); do
[19]434 local CMD=$(lowercase "${C#sdtdCommand}")
[17]435 printf "%s " "$CMD"
436 done
437}
438
439. /usr/local/lib/7dtd/help.sh
[19]440. /usr/local/lib/7dtd/serverconfig.sh
[17]441for M in /usr/local/lib/7dtd/commands/*.sh; do
442 . $M
443done
444
[64]445checkRootLoadConf
446
Note: See TracBrowser for help on using the repository browser.