나의 사이트 수정
This commit is contained in:
15
deploy/genesis.env.example
Normal file
15
deploy/genesis.env.example
Normal file
@@ -0,0 +1,15 @@
|
||||
# 서버의 /srv/genesis/genesis.env 로 복사해 값을 채운다.
|
||||
#
|
||||
# sudo cp deploy/genesis.env.example /srv/genesis/genesis.env
|
||||
# sudo nano /srv/genesis/genesis.env
|
||||
# sudo chown genesis:genesis /srv/genesis/genesis.env
|
||||
# sudo chmod 600 /srv/genesis/genesis.env
|
||||
#
|
||||
# systemd 가 읽는 형식이라 KEY=VALUE 한 줄씩, 따옴표는 붙이지 않는다.
|
||||
# 값 안에 $ 가 있으면 systemd 가 변수로 해석하므로 $$ 로 두 번 쓴다.
|
||||
#
|
||||
# 여기 넣은 값이 appsettings.json 보다 우선한다.
|
||||
|
||||
ConnectionStrings__DefaultConnection=Server=152.69.235.249;Port=3306;Database=mygame;Uid=root;Pwd=여기에-DB-비밀번호;
|
||||
Portfolio__AdminPassword=여기에-관리자-비밀번호
|
||||
Portfolio__MaxUploadBytes=104857600
|
||||
42
deploy/genesis.service
Normal file
42
deploy/genesis.service
Normal file
@@ -0,0 +1,42 @@
|
||||
# systemd 서비스 등록 파일.
|
||||
# 서버에서:
|
||||
# sudo cp deploy/genesis.service /etc/systemd/system/
|
||||
# sudo systemctl daemon-reload
|
||||
# sudo systemctl enable --now genesis
|
||||
#
|
||||
# 경로나 사용자 이름을 바꿨다면 아래 값도 함께 고치세요.
|
||||
|
||||
[Unit]
|
||||
Description=Genesis 게임 서버 + 포트폴리오 사이트
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
# 실행 파일과 wwwroot, appsettings.json 이 함께 있는 폴더
|
||||
WorkingDirectory=/srv/genesis
|
||||
ExecStart=/srv/genesis/GameServer
|
||||
|
||||
# 비밀값은 이 파일에서 읽는다. (git 에 올리지 않는다)
|
||||
EnvironmentFile=/srv/genesis/genesis.env
|
||||
|
||||
Environment=ASPNETCORE_ENVIRONMENT=Production
|
||||
# 0.0.0.0 이어야 외부에서 접속된다. nginx 를 앞에 둔다면 127.0.0.1 로 좁히세요.
|
||||
Environment=ASPNETCORE_URLS=http://0.0.0.0:5281
|
||||
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
|
||||
|
||||
User=genesis
|
||||
Group=genesis
|
||||
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
# .NET 은 SIGINT 를 받아야 정상 종료한다. (기본 SIGTERM 이면 강제 종료됨)
|
||||
KillSignal=SIGINT
|
||||
SyslogIdentifier=genesis
|
||||
|
||||
# 최소한의 격리. 업로드 폴더에는 써야 하므로 전체 읽기전용은 걸지 않는다.
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ProtectHome=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
115
deploy/healthcheck.sh
Normal file
115
deploy/healthcheck.sh
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
# 배포 후 서버가 제대로 떴는지 확인한다. 서버에서 실행한다.
|
||||
#
|
||||
# ./healthcheck.sh # 기본 http://localhost:5000
|
||||
# ./healthcheck.sh 5281 # 포트만 바꿔서
|
||||
# ./healthcheck.sh 5000 GameServer # 서비스 이름까지 지정
|
||||
# ./healthcheck.sh 5000 GameServer /home/ubuntu/gameserver # 앱 폴더까지
|
||||
#
|
||||
# 실패한 항목이 하나라도 있으면 종료 코드 1 을 돌려준다.
|
||||
|
||||
BASE="http://localhost:${1:-5000}"
|
||||
SERVICE="${2:-GameServer}"
|
||||
# 앱 폴더(GameServer 실행 파일과 wwwroot 가 있는 곳). 기본은 이 스크립트가 있는 폴더.
|
||||
APPDIR="${3:-$(cd "$(dirname "$0")" && pwd)}"
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
ok() { PASS=$((PASS+1)); printf ' \033[32mOK \033[0m %s\n' "$1"; }
|
||||
bad() { FAIL=$((FAIL+1)); printf ' \033[31m실패\033[0m %s\n %s\n' "$1" "$2"; }
|
||||
|
||||
# code URL -> 응답 코드만
|
||||
code() { curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$1" 2>/dev/null; }
|
||||
|
||||
echo
|
||||
echo "=== 1. 서비스 상태 ==="
|
||||
if systemctl is-active --quiet "$SERVICE" 2>/dev/null; then
|
||||
ok "$SERVICE 실행 중"
|
||||
since=$(systemctl show -p ActiveEnterTimestamp --value "$SERVICE" 2>/dev/null)
|
||||
[ -n "$since" ] && echo " 시작: $since"
|
||||
# 계속 죽었다 살아나는 중인지
|
||||
n=$(systemctl show -p NRestarts --value "$SERVICE" 2>/dev/null || echo 0)
|
||||
if [ "${n:-0}" -gt 0 ]; then
|
||||
echo " 재시작 횟수: $n (반복되면 로그를 확인하세요)"
|
||||
fi
|
||||
else
|
||||
bad "$SERVICE 가 실행 중이 아님" "sudo systemctl status $SERVICE"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== 2. 포트 열림 ==="
|
||||
PORT="${1:-5000}"
|
||||
if ss -tln 2>/dev/null | grep -q ":$PORT "; then
|
||||
ok "포트 $PORT 수신 중"
|
||||
ss -tlnp 2>/dev/null | grep ":$PORT " | sed 's/^/ /'
|
||||
else
|
||||
bad "포트 $PORT 가 열려 있지 않음" "sudo ss -tlnp | grep $PORT"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== 3. 기존 게임 API (회귀 확인) ==="
|
||||
for p in /myGame/playableCharacters /myGame/userCharacters; do
|
||||
c=$(code "$BASE$p")
|
||||
if [ "$c" = "200" ]; then ok "GET $p"
|
||||
else bad "GET $p -> $c" "DB 연결이나 라우팅을 확인하세요"; fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "=== 4. 포트폴리오 ==="
|
||||
c=$(code "$BASE/api/portfolio/categories")
|
||||
if [ "$c" = "200" ]; then
|
||||
ok "카테고리 API"
|
||||
n=$(curl -s --max-time 10 "$BASE/api/portfolio/categories" | grep -o '"categoryNo"' | wc -l)
|
||||
echo " 카테고리 $n 개"
|
||||
[ "$n" -eq 0 ] && echo " (0 개면 DB 스키마 생성이 실패했을 수 있습니다. 로그를 보세요)"
|
||||
else
|
||||
bad "카테고리 API -> $c" "DB 연결 실패일 가능성이 큽니다"
|
||||
fi
|
||||
|
||||
c=$(code "$BASE/api/portfolio/posts")
|
||||
[ "$c" = "200" ] && ok "게시물 API" || bad "게시물 API -> $c" ""
|
||||
|
||||
echo
|
||||
echo "=== 5. 사이트 (정적 파일) ==="
|
||||
for p in / /css/style.css /js/app.js; do
|
||||
c=$(code "$BASE$p")
|
||||
if [ "$c" = "200" ]; then ok "GET $p"
|
||||
else bad "GET $p -> $c" "wwwroot 가 함께 배포됐는지 확인하세요"; fi
|
||||
done
|
||||
|
||||
echo
|
||||
echo "=== 6. 업로드 폴더 쓰기 권한 ==="
|
||||
UPDIR="$APPDIR/wwwroot/uploads"
|
||||
if [ -d "$UPDIR" ]; then
|
||||
if [ -w "$UPDIR" ]; then ok "쓰기 가능 ($UPDIR)"
|
||||
else bad "쓰기 불가 ($UPDIR)" "서비스 실행 사용자에게 권한을 주세요"; fi
|
||||
echo " 보관된 파일 $(find "$UPDIR" -type f ! -name '.gitkeep' 2>/dev/null | wc -l) 개"
|
||||
else
|
||||
bad "업로드 폴더 없음 ($UPDIR)" "mkdir -p '$UPDIR'"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== 7. 최근 오류 로그 ==="
|
||||
# grep -c 는 일치가 없으면 0 을 출력하고 종료코드 1 을 낸다.
|
||||
# '|| echo 0' 을 붙이면 0 이 두 번 나와 숫자 비교가 깨지므로 쓰지 않는다.
|
||||
errs=$(journalctl -u "$SERVICE" -n 200 --no-pager 2>/dev/null | grep -icE 'fail|error|exception')
|
||||
errs=$(printf '%s' "${errs:-0}" | head -1)
|
||||
case "$errs" in ''|*[!0-9]*) errs=0 ;; esac
|
||||
|
||||
if [ "$errs" -eq 0 ]; then
|
||||
ok "최근 200줄에 오류 없음"
|
||||
else
|
||||
echo " 오류로 보이는 줄 $errs 개 — 확인:"
|
||||
journalctl -u "$SERVICE" -n 200 --no-pager 2>/dev/null \
|
||||
| grep -iE 'fail|error|exception' | tail -5 | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "================================"
|
||||
printf ' 통과 %d 실패 %d\n' "$PASS" "$FAIL"
|
||||
echo "================================"
|
||||
if [ "$FAIL" -gt 0 ]; then
|
||||
echo
|
||||
echo "로그 전체 보기: sudo journalctl -u $SERVICE -n 100 --no-pager"
|
||||
exit 1
|
||||
fi
|
||||
5
deploy/publish-linux.cmd
Normal file
5
deploy/publish-linux.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
REM PowerShell 실행 정책을 바꾸지 않고 게시 스크립트를 실행한다.
|
||||
REM publish-linux.cmd
|
||||
REM publish-linux.cmd -Target user@서버주소
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0publish-linux.ps1" %*
|
||||
144
deploy/publish-linux.ps1
Normal file
144
deploy/publish-linux.ps1
Normal file
@@ -0,0 +1,144 @@
|
||||
# 리눅스용 자체 포함 실행 파일을 만든다. (윈도우 PowerShell 용)
|
||||
# bash 가 필요 없다. VS Code 기본 터미널에서 그대로 돌아간다.
|
||||
#
|
||||
# .\deploy\publish-linux.ps1
|
||||
# .\deploy\publish-linux.ps1 -Target ubuntu@서버주소 # 만들고 복사까지
|
||||
#
|
||||
# 경로·서비스 이름이 다르면:
|
||||
# .\deploy\publish-linux.ps1 -Target ubuntu@서버 `
|
||||
# -RemoteDir /home/ubuntu/gameserver -Service GameServer
|
||||
#
|
||||
# 서버에는 .NET 을 설치할 필요가 없다.
|
||||
|
||||
param(
|
||||
[string]$Target = "",
|
||||
[string]$RemoteDir = "/srv/genesis",
|
||||
# 비우면 서버에서 자동으로 찾는다.
|
||||
[string]$Service = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# 저장소 루트로 이동 (이 스크립트는 deploy/ 안에 있다)
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
Set-Location $root
|
||||
|
||||
$project = "GameServer/GameServer.csproj"
|
||||
$out = "artifacts/linux-x64"
|
||||
|
||||
Write-Host "== 1) 빌드 ==" -ForegroundColor Cyan
|
||||
if (Test-Path $out) { Remove-Item $out -Recurse -Force }
|
||||
|
||||
dotnet publish $project `
|
||||
-c Release `
|
||||
-r linux-x64 `
|
||||
--self-contained true `
|
||||
-p:PublishSingleFile=true `
|
||||
-p:EnableCompressionInSingleFile=true `
|
||||
-p:DebugType=none `
|
||||
-p:DebugSymbols=false `
|
||||
-o $out `
|
||||
--nologo
|
||||
if ($LASTEXITCODE -ne 0) { throw "publish 실패" }
|
||||
|
||||
# 개발용 설정은 서버로 보내지 않는다.
|
||||
Remove-Item "$out/appsettings.Development.json" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# 서버에서 바로 띄울 실행 스크립트.
|
||||
# - ASPNETCORE_URLS 가 없으면 localhost:5000 에만 묶여 외부에서 안 보인다.
|
||||
# - 윈도우에서 복사하면 실행 권한이 사라지므로 스스로 chmod 한다.
|
||||
# 반드시 LF 로 저장해야 한다. CRLF 면 리눅스에서 "bad interpreter" 로 죽는다.
|
||||
$runSh = @(
|
||||
'#!/usr/bin/env bash',
|
||||
'# 서버에서 이 폴더로 들어와 ./run.sh 하면 바로 뜬다.',
|
||||
'# PORT=8080 ./run.sh 처럼 포트를 바꿀 수 있다.',
|
||||
'set -euo pipefail',
|
||||
'cd "$(dirname "$0")"',
|
||||
'',
|
||||
'PORT="${PORT:-5281}"',
|
||||
'',
|
||||
'chmod +x ./GameServer 2>/dev/null || true',
|
||||
'mkdir -p wwwroot/uploads',
|
||||
'',
|
||||
'# 0.0.0.0 이어야 바깥에서 접속된다. 127.0.0.1 로 두면 서버 안에서만 보인다.',
|
||||
'export ASPNETCORE_URLS="http://0.0.0.0:${PORT}"',
|
||||
'export ASPNETCORE_ENVIRONMENT=Production',
|
||||
'',
|
||||
'# genesis.env 가 있으면 거기 값이 appsettings.json 보다 우선한다.',
|
||||
'if [ -f ./genesis.env ]; then',
|
||||
' set -a; . ./genesis.env; set +a',
|
||||
'fi',
|
||||
'',
|
||||
'echo "http://0.0.0.0:${PORT} 에서 실행합니다. (Ctrl+C 로 종료)"',
|
||||
'exec ./GameServer',
|
||||
''
|
||||
) -join "`n"
|
||||
|
||||
# UTF-8(BOM 없음) + LF 로 기록
|
||||
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||||
[System.IO.File]::WriteAllText((Join-Path $root "$out/run.sh"), $runSh, $utf8NoBom)
|
||||
|
||||
# 배포 후 확인 스크립트도 함께 넣는다.
|
||||
Copy-Item (Join-Path $PSScriptRoot "healthcheck.sh") "$out/" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
$size = "{0:N0} MB" -f ((Get-ChildItem $out -Recurse -File | Measure-Object Length -Sum).Sum / 1MB)
|
||||
Write-Host ""
|
||||
Write-Host " 산출물: $out ($size)" -ForegroundColor Green
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Target)) {
|
||||
Write-Host ""
|
||||
Write-Host " 서버로 올리려면:" -ForegroundColor Yellow
|
||||
Write-Host " .\deploy\publish-linux.ps1 -Target user@서버주소"
|
||||
Write-Host ""
|
||||
Write-Host " 직접 복사한다면:"
|
||||
Write-Host " scp -r $out/* user@서버주소:$RemoteDir/"
|
||||
Write-Host " ssh user@서버주소 `"cd $RemoteDir && chmod +x run.sh && ./run.sh`""
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "== 2) 업로드 ==" -ForegroundColor Cyan
|
||||
Write-Host " 대상: ${Target}:$RemoteDir"
|
||||
|
||||
# scp 는 지우지 않고 덮어쓰기만 한다.
|
||||
# 산출물에 wwwroot/uploads 가 없으므로 서버의 사진은 그대로 남는다.
|
||||
ssh $Target "mkdir -p '$RemoteDir'"
|
||||
if ($LASTEXITCODE -ne 0) { throw "서버 접속 실패" }
|
||||
|
||||
scp -r "$out/*" "${Target}:$RemoteDir/"
|
||||
if ($LASTEXITCODE -ne 0) { throw "복사 실패" }
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "== 3) 마무리 ==" -ForegroundColor Cyan
|
||||
|
||||
# 서버에서 실행할 명령. 작은따옴표 here-string 이라 PowerShell 이 손대지 않는다.
|
||||
$remoteScript = @'
|
||||
set -e
|
||||
cd "__DIR__"
|
||||
chmod +x GameServer run.sh
|
||||
mkdir -p wwwroot/uploads
|
||||
echo " 실행 권한 설정 완료"
|
||||
|
||||
SVC="__SVC__"
|
||||
if [ -z "$SVC" ]; then
|
||||
for c in GameServer genesis gameserver portfolio; do
|
||||
if systemctl list-unit-files 2>/dev/null | grep -q "^$c.service"; then SVC="$c"; break; fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n "$SVC" ]; then
|
||||
sudo systemctl restart "$SVC" && echo " $SVC 서비스 재시작"
|
||||
else
|
||||
echo " systemd 서비스를 찾지 못했습니다. ./run.sh 로 직접 실행하세요."
|
||||
fi
|
||||
'@
|
||||
|
||||
$remoteScript = $remoteScript.Replace('__DIR__', $RemoteDir).Replace('__SVC__', $Service)
|
||||
$remoteScript | ssh $Target "bash -s"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "완료. 서버에서 실행하려면:" -ForegroundColor Green
|
||||
Write-Host " ssh $Target"
|
||||
Write-Host " cd $RemoteDir && ./run.sh"
|
||||
Write-Host ""
|
||||
Write-Host " (계속 띄워 두려면 README 5절의 systemd 등록을 참고하세요)"
|
||||
124
deploy/publish-linux.sh
Normal file
124
deploy/publish-linux.sh
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env bash
|
||||
# 리눅스용 자체 포함 실행 파일을 만들고 서버로 올린다.
|
||||
# 윈도우(Git Bash)·맥·리눅스 어디서 돌려도 된다. 서버에는 .NET 을 설치할 필요가 없다.
|
||||
#
|
||||
# ./deploy/publish-linux.sh # 빌드만
|
||||
# ./deploy/publish-linux.sh ubuntu@서버 # 빌드 후 업로드까지
|
||||
#
|
||||
# 경로·서비스 이름이 다르면 환경변수로 준다:
|
||||
# REMOTE_DIR=/home/ubuntu/gameserver SERVICE=GameServer # ./deploy/publish-linux.sh ubuntu@서버
|
||||
#
|
||||
# 업로드된 사진(wwwroot/uploads)은 건드리지 않는다.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT="GameServer/GameServer.csproj"
|
||||
OUT="artifacts/linux-x64"
|
||||
TARGET="${1-}"
|
||||
REMOTE_DIR="${REMOTE_DIR:-/srv/genesis}"
|
||||
# 비우면 서버에서 자동으로 찾는다.
|
||||
SERVICE="${SERVICE:-}"
|
||||
|
||||
echo "== 1) 빌드 =="
|
||||
rm -rf "$OUT"
|
||||
dotnet publish "$PROJECT" \
|
||||
-c Release \
|
||||
-r linux-x64 \
|
||||
--self-contained true \
|
||||
-p:PublishSingleFile=true \
|
||||
-p:EnableCompressionInSingleFile=true \
|
||||
-p:DebugType=none \
|
||||
-p:DebugSymbols=false \
|
||||
-o "$OUT" \
|
||||
--nologo
|
||||
|
||||
# 개발용 설정은 서버로 보내지 않는다.
|
||||
rm -f "$OUT/appsettings.Development.json"
|
||||
|
||||
# 서버에서 바로 띄울 수 있는 실행 스크립트를 함께 넣는다.
|
||||
# - ASPNETCORE_URLS 를 지정하지 않으면 localhost:5000 에만 묶여 외부에서 안 보인다.
|
||||
# - 윈도우에서 복사하면 실행 권한이 사라지므로 여기서 다시 붙인다.
|
||||
cat > "$OUT/run.sh" <<'RUNSH'
|
||||
#!/usr/bin/env bash
|
||||
# 서버에서 이 폴더로 들어와 ./run.sh 하면 바로 뜬다.
|
||||
# PORT=8080 ./run.sh 처럼 포트를 바꿀 수 있다.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
PORT="${PORT:-5281}"
|
||||
|
||||
chmod +x ./GameServer 2>/dev/null || true
|
||||
mkdir -p wwwroot/uploads
|
||||
|
||||
# 0.0.0.0 이어야 바깥에서 접속된다. 127.0.0.1 로 두면 서버 안에서만 보인다.
|
||||
export ASPNETCORE_URLS="http://0.0.0.0:${PORT}"
|
||||
export ASPNETCORE_ENVIRONMENT=Production
|
||||
|
||||
# genesis.env 가 있으면 거기 값이 appsettings.json 보다 우선한다.
|
||||
if [ -f ./genesis.env ]; then
|
||||
set -a; . ./genesis.env; set +a
|
||||
fi
|
||||
|
||||
echo "http://0.0.0.0:${PORT} 에서 실행합니다. (Ctrl+C 로 종료)"
|
||||
exec ./GameServer
|
||||
RUNSH
|
||||
chmod +x "$OUT/run.sh"
|
||||
|
||||
# 배포 후 확인 스크립트도 함께 넣는다.
|
||||
cp "$(dirname "$0")/healthcheck.sh" "$OUT/" 2>/dev/null || true
|
||||
chmod +x "$OUT/healthcheck.sh" 2>/dev/null || true
|
||||
|
||||
echo
|
||||
echo " 산출물: $OUT ($(du -sh "$OUT" | cut -f1))"
|
||||
|
||||
if [ -z "$TARGET" ]; then
|
||||
echo
|
||||
echo " 서버로 올리려면: $0 user@서버주소"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "== 2) 업로드 =="
|
||||
echo " 대상: $TARGET:$REMOTE_DIR"
|
||||
|
||||
ssh "$TARGET" "mkdir -p '$REMOTE_DIR'"
|
||||
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
# rsync 가 있으면 지운 파일까지 맞춰 준다.
|
||||
# 다만 uploads 와 비밀값 파일은 제외해 서버 것을 남긴다.
|
||||
rsync -avz --delete --exclude 'wwwroot/uploads/' --exclude 'genesis.env' --exclude 'appsettings.Production.json' "$OUT/" "$TARGET:$REMOTE_DIR/"
|
||||
else
|
||||
# 윈도우 Git Bash 에는 보통 rsync 가 없다. scp 로 보낸다.
|
||||
# scp 는 덮어쓰기만 하고 지우지 않으므로 서버의 사진은 그대로 남는다.
|
||||
echo " rsync 가 없어 scp 로 보냅니다."
|
||||
# 산출물에 appsettings.Production.json 이 없으므로 서버 것이 덮어써지지 않는다.
|
||||
scp -r "$OUT"/* "$TARGET:$REMOTE_DIR/"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "== 3) 마무리 =="
|
||||
# 윈도우에서 복사하면 실행 권한이 사라진다. 서버에서 다시 붙인다.
|
||||
ssh "$TARGET" "
|
||||
cd '$REMOTE_DIR' &&
|
||||
chmod +x GameServer run.sh &&
|
||||
mkdir -p wwwroot/uploads &&
|
||||
echo ' 실행 권한 설정 완료'
|
||||
|
||||
SVC='$SERVICE'
|
||||
# 이름을 안 줬으면 이 폴더를 실행하는 서비스를 찾아본다.
|
||||
if [ -z \"\$SVC\" ]; then
|
||||
for c in GameServer genesis gameserver portfolio; do
|
||||
if systemctl list-unit-files 2>/dev/null | grep -q \"^\$c.service\"; then SVC=\$c; break; fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -n \"\$SVC\" ]; then
|
||||
sudo systemctl restart \"\$SVC\" && echo \" \$SVC 서비스 재시작\"
|
||||
else
|
||||
echo ' systemd 서비스를 찾지 못했습니다. ./run.sh 로 직접 실행하세요.'
|
||||
fi
|
||||
"
|
||||
|
||||
echo
|
||||
echo "완료."
|
||||
echo " 바로 띄워 보려면: ssh $TARGET \"cd $REMOTE_DIR && ./run.sh\""
|
||||
Reference in New Issue
Block a user