◾️ 개요
24시간으로 서버 운영을 하게되면 발생하는 문제가 하나 있는데
팰 주위에 유저가 아무도 없는 경우, 아예 AI가 활성화되지 않아서 아무것도 먹지 않고 움직이지 않아 팰이 금방 병에 걸리게 된다.
해당 오류에 대해 패치 예정이 없는 지금으로써는 팰 주위에 사람을 두는게 유일한 해결법이다.
또는, 사람이 없으면 서버를 잠시 일시정지(Docker로 서버를 배포한 경우에만 해당) 하거나.
지금부터 만들어볼 스크립트의 구동 방식은 아래와 같다.
- 1분마다 사용자 수 확인
- 사용자가 아무도 없으면 서버 재시작(램 최적화,
docker restart
ordocker-compose restart
)후 서버 일시정지(docker pause
ordocker-compose pause
)
- 사용자가 아무도 없으면 서버 재시작(램 최적화,
- 서버 일시정지 상태
- 무한 루프를 돌면서 외부망 포트로 들어오는 TCP 트래픽을 계속 탐색
- 접속 시도 발견 시 서버 재기동
▪️ 구동 환경
- Ubuntu 22.04.03
- Docker >= 1.13
- Docker Compopse >= 1.13
- Palworld Docker image
▪️ 사전 준비
tcpdump
설치
sudo apt-get install -y tcpdump
▪️ 스크립트 작성
import subprocess
import time
class StatusCheck():
def __init__(self) -> None:
self._TARGET_PORT : int = 8211
self._CONTAINER_NAME : str = "palworld-server"
def _check_players(self) -> bool:
players_output: str = self._run_command(command=f"docker exec -i {self._CONTAINER_NAME} rcon-cli ShowPlayers")
if players_output:
# 플레이어 목록
players = [player.replace('\x00','') for player in players_output.split('\n')[1:]]
if len(players) != 0:
return True
else:
return False
def _run_command(self,command: str | tuple) -> str:
return subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, text=True).stdout.strip()
def main() -> None:
# Create StatusCheck instance
status: StatusCheck = StatusCheck()
while True:
# 플레이어 목록 조회
player: bool = status._check_players()
if not player:
print("No Players found. Restart the server")
status._run_command(command=f'docker restart {status._CONTAINER_NAME}')
# wait for server to restart
for sec in range(30, 0, -1):
print(f'pausing in {sec} seconds')
time.sleep(1)
# if not players, pause server
if not status._check_players():
print('Restart Complete. Pause the server')
status._run_command(f'docker pause {status._CONTAINER_NAME}')
else:
player = True
while not player:
# use tcpdump to capture incoming traffic on the target port
capture_command = (f"sudo tcpdump -n -c 1 -i any port {status._TARGET_PORT} 2>/dev/null")
capture_result: str = status._run_command(command=capture_command)
# Check if any packets were caputerd
if capture_result:
player = True
print(f'Connection attempt detected on port {status._TARGET_PORT}')
print(f"Starting server")
status._run_command(command=f'docker unpause {status._CONTAINER_NAME}')
# after unpausing the server, wait for players to connect
for sec in range(60,0,-1):
print(f'checking in {sec} seconds')
time.sleep(1)
else:
time.sleep(1)
else:
print('Players found. server will continue running.')
time.sleep(60)
if __name__ == '__main__':
main()
스크립트 실행
nohup python3 main.py > log 2>&1 &