1)
Is it possible for a bash shell script to query a game server and determine if it’s empty or has players? If so, how is this done? (Even if you'd need a c++ extension installed to do so, I'd be willing to do the research with an idea of how it would work.)
2)
Is it possible for a shell script to monitor a screen session for a key word? The sourcemod equivalent of adding a command listener.
"MasterRequestRestart" is the word I'm wanting to pick up.
There's a couple of ways. You can either send the A2S_INFO (Source Server) query via some application, use a standalone rcon tool to read the status output, or write some plugin using the socket extension to respond with your desired info
Don't think so. Not sure if the logging facilities would catch that.
There's a couple of ways. You can either send the A2S_INFO (Source Server) query via some application, use a standalone rcon tool to read the status output, or write some plugin using the socket extension to respond with your desired info
Don't think so. Not sure if the logging facilities would catch that.
I've compiled the rcon tool, but I'm not sure if I'm using it correctly.
In this example, the rcon password is just a made up password.
Code:
root@testsvrchi:~# ./rcon --help
Usage: <programname> --rcon="<ip> <port> <rconpw> <cmd>"
Example: --rcon="127.0.0.1 27960 myrconpw devmap oasis"
root@testsvrchi:~# ./rcon --rcon="74.91.124.177 27015 rconpassword101 status"
Sending:
¦¦¦¦rcon rconpassword101 status
Could not receive.
Not sure if there's a more specific rcon command to query "players - humans" count, or if it's something that would have to be parsed from the status command.
Code:
] rcon status
hostname: Left 4 Dead 2
version : 2.1.5.2 7149 secure (unknown)
udp/ip : 74.91.124.177:27015 [ public same ]
os : Linux Dedicated
map : c2m1_highway
players : 1 humans, 0 bots (4 max) (not hibernating) (reserved 186000000a383ab)
Edit:
Haven't worked with c++ / c before, but it looks like the error is stemming from this returning -1:
ip = "10.0.0.1"
port = 27015
password = "rconpassword"
def isEmpty(address, password):
with valve.rcon.RCON(address, password) as rcon:
response = rcon.execute("status")
response_text = response.body.decode('ascii', 'ignore')
for line in response_text.splitlines():
if "players :" in line:
for words in ['0 humans']:
if re.search(r'\b' + words + r'\b', line):
return True
else:
return False
else:
pass
if __name__ == "__main__":
if isEmpty((ip, port), password):
print("server is empty")
else:
print("server is NOT empty")
@ hustl4
Thanks for the idea. The script appears to be getting hung up. If you do happen to test it out - would you mind uploading it to github so I can include a direct download for the script I'm currently writing? Would be best if there was safeguards against situations where it might get hung up - maybe there could be a timeout feature if the server doesn't respond in x amount of time there's a certain return value. (Since this script is designed to get launched automatically from a cron job task.)
In regards to the auto-updating:
- I can use screen to log output to a file and successfully added update functionality there, but the problem is when you have multiple servers on the same machine and need to make a unique log file name that's the same as the screen session (socket) name.
- Some users say to use tmux instead of screen, so I spent the better part of a day writing out a script to handle auto-launching X amount of servers:
(I still have to make the tmux log.)
Spoiler
PHP Code:
#!/bin/bash
####################### # # This script should be launched every minute from a cron job task. # # It's mainly for lazy admins who prefer to have their servers & custom maps updated automatically, # and who also likely have in-game sourcemod plugins installed which shut down # the game server after certain events (e.g. https://forums.alliedmods.net/showthread.php?t=306494 ) # # Session Names should be unique, one shouldn't overlap entirely from another. # e.g. L4D2_server & L4D2_server2 would be problematic. # #######################
Launch_Any_Offline_Servers() { for ((j=0;j<$num_of_servers;j++)); do
Print_Configuration $j
#TODO: find better method for detecting if server's offline using tmux # This method can (rarely) return a false positive ( https://i.imgur.com/UDsFTil.png ) hence the need for 3 checks before launching.. echo "Initiating server check." sleep 3s echo ""
alive=`ps ux | grep "${SessionName[$j]}" | wc -l | awk '{ print $1 }'` if [ $alive -lt 2 ]; then echo "First check: server ${SessionName[$j]} appears to be offline." sleep 3s alive2=`ps ux | grep "${SessionName[$j]}" | wc -l | awk '{ print $1 }'` if [ $alive2 -lt 2 ]; then echo "Second check: server ${SessionName[$j]} is still offline." sleep 3s alive3=`ps ux | grep "${SessionName[$j]}" | wc -l | awk '{ print $1 }'` if [ $alive3 -lt 2 ]; then echo "Third check: server ${SessionName[$j]} is still offline." if [ -n "${WorkShopDirectory[$j]}" ]; then if [ -n "${WorkshopCollection[$j]}" ]; then echo "" echo "Checking for workshop map updates before launching server." sleep 2s if [ ! -e "steam_workshop_downloader.py" ]; then echo "Workshop downloader not found. Manually downloading file.." #In case valve server is down - this version of workshop DL'er caps failed downloads at 25 retries curl -o steam_workshop_downloader.py 'https://raw.githubusercontent.com/nosoop/steam_workshop_downloader/commed-patch/workshop.py' chmod +x steam_workshop_downloader.py fi ./steam_workshop_downloader.py -o "${WorkShopDirectory[$j]}" "${WorkshopCollection[$j]}" echo "" echo "Workshop Update Complete." echo "" fi fi #LAUNCH SERVER HERE echo "Launching server.." tmux new-session -d -s "${SessionName[$j]}" "${srcds_run[$j]}${Parameters[$j]}" #NEED TO ADD LOG HERE sleep 3s else echo "Third check: ${SessionName[$j]} already online. Skipping.." sleep 3s fi else echo "Second check: ${SessionName[$j]} already running. Skipping.." sleep 3s fi else echo "First check: ${SessionName[$j]} already running. Skipping..." sleep 3s fi done }
Print_Configuration() { sleep 1s echo "-----------------------------------------------------" echo "" echo "Checking for ${SessionName[$1]} in 3" sleep 1s echo "Checking for ${SessionName[$1]} in 2.." sleep 1s echo "Checking for ${SessionName[$1]} in 1"... sleep 1s clear echo "###########################" echo "SERVER CONFIGURATION:" echo "Launch Path: ${srcds_run[$1]}" echo echo "Launch Parameters: ${Parameters[$1]}" echo echo "Update Script: ${UpdateScript[$1]}" echo echo echo "CUSTOM MAP SETTINGS:" if [ -n "${WorkShopDirectory[$1]}" ]; then echo "Workshop Directory: ${WorkShopDirectory[$1]}" else echo "No workshop directory detected." fi echo if [ -n "${WorkshopCollection[$1]}" ]; then echo "Workshop Collection: ${WorkshopCollection[$1]}" else echo "No workshop collection detected." fi echo echo sleep 4s echo "Continuing in 3" sleep 1s echo "Continuing in 2.." sleep 1s echo "Continuing in 1..." sleep 1s clear }
Check_Input() { if [ -z "$num_of_servers" ]; then echo "Error: Variable left blank: 'num_of_servers'." exit 1 fi
#Make sure all non-optional fields are completed. typeset -n x for x in SessionName srcds_run Parameters UpdateScript ServerPort RconPassword; do for((j=0;j<$num_of_servers;j++)); do if [ -z "${x[$j]}" ]; then echo "Error: One or more non-optional items left blank." exit 1 fi done done echo "Initialization Check successfull." }
# This script is run every minute from a cron job task # So this will get executed @ 3am every morning. Time_Var=$(date +%H%M) if [ "$Time_Var" -eq 0300 ]; then echo "It is currently 3am. $(date +%H:%M:%S)" > /tmp/Test.output #test #TODO add update functionality here #TODO Python script: check each server (twice to be sure) for human players. #TODO Shut down each server that's empty while counting # If empty server count = num_of_servers, execute 'reboot' command. fi
Check_Input Launch_Any_Offline_Servers
- Come to find out after all that work, the latest version of tmux may not be compatible with creating dynamic log names (if i revert to an older version of tmux and ever 'apt-get update', it may break the script): https://github.com/GameServerManager..._start.sh#L113
Anyway, if that's the case I'll just use something similar to what hustl4 posted. If all game servers are all detected as empty on some night, they'll all get an update then the physical server will do a reboot. The cron job task will relaunch the script ^ and the servers will be back online.
Last edited by dustinandband; 10-16-2018 at 11:41.
@ hustl4
Thanks for the idea. The script appears to be getting hung up. If you do happen to test it out - would you mind uploading it to github so I can include a direct download for the script I'm currently writing? Would be best if there was safeguards against situations where it might get hung up - maybe there could be a timeout feature if the server doesn't respond in x amount of time there's a certain return value. (Since this script is designed to get launched automatically from a cron job task.)
sorry, should have mentioned only tested on python3.6 on a mix of centos 7 and ubuntu 16.04 (csgo servers)
I have it running in cron every minute (cpu mining crypto when servers are empty lmao)
I added a timeout exception and uploaded to github https://gist.github.com/wh1te909/82f...7fed2b8fd7dcf8