fix: check.sh — не падать до docker compose, проверка после старта
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -25,17 +25,17 @@ cd shop3
|
|||||||
chmod +x install.sh check.sh
|
chmod +x install.sh check.sh
|
||||||
./install.sh
|
./install.sh
|
||||||
|
|
||||||
# 3. Проверка версий
|
# 3. Запуск
|
||||||
./check.sh
|
|
||||||
|
|
||||||
# 4. Запуск
|
|
||||||
docker compose up --build -d
|
docker compose up --build -d
|
||||||
|
|
||||||
|
# 4. Проверка (после старта контейнеров)
|
||||||
|
./check.sh --after-start
|
||||||
```
|
```
|
||||||
|
|
||||||
Одной цепочкой (после клона введите ответы установщика):
|
Одной цепочкой (после клона введите ответы установщика):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.evilfox.cc/test/shop3.git && cd shop3 && chmod +x install.sh check.sh && ./install.sh && ./check.sh && docker compose up --build -d
|
git clone https://git.evilfox.cc/test/shop3.git && cd shop3 && chmod +x install.sh check.sh && ./install.sh && docker compose up --build -d && ./check.sh --after-start
|
||||||
```
|
```
|
||||||
|
|
||||||
С Go на сервере вместо `install.sh`:
|
С Go на сервере вместо `install.sh`:
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
# Проверка версий: Go, Docker, PostgreSQL
|
# Проверка версий (до или после docker compose)
|
||||||
|
param([switch]$AfterStart)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
Set-Location $PSScriptRoot
|
Set-Location $PSScriptRoot
|
||||||
go run ./cmd/check
|
|
||||||
|
if ($AfterStart) {
|
||||||
|
& "$PSScriptRoot\check.sh" --after-start
|
||||||
|
} else {
|
||||||
|
& bash "$PSScriptRoot\check.sh" 2>$null
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
$env:CHECK_SKIP_DB = "1"
|
||||||
|
go run ./cmd/check
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,67 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
if command -v go >/dev/null 2>&1; then
|
|
||||||
go run ./cmd/check
|
MODE="${1:-pre}"
|
||||||
else
|
|
||||||
docker run --rm -v "$(pwd):/app" -w /app golang:1.22-alpine go run ./cmd/check
|
host_docker_check() {
|
||||||
fi
|
if command -v docker >/dev/null 2>&1; then
|
||||||
|
if docker version >/dev/null 2>&1; then
|
||||||
|
echo " ✓ docker: $(docker version --format '{{.Server.Version}}' 2>/dev/null || docker --version)"
|
||||||
|
else
|
||||||
|
echo " ! docker: установлен, но демон недоступен (запустите docker)"
|
||||||
|
fi
|
||||||
|
if docker compose version >/dev/null 2>&1; then
|
||||||
|
echo " ✓ docker_compose: $(docker compose version --short 2>/dev/null || docker compose version)"
|
||||||
|
else
|
||||||
|
echo " ! docker_compose: не найден"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ! docker: не найден на хосте"
|
||||||
|
echo " ! docker_compose: не найден на хосте"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_go_check() {
|
||||||
|
if command -v go >/dev/null 2>&1; then
|
||||||
|
CHECK_HOST_TOOLS=1 "$@" go run ./cmd/check
|
||||||
|
else
|
||||||
|
CHECK_HOST_TOOLS=0 "$@" docker run --rm -v "$(pwd):/app" -w /app golang:1.22-alpine go run ./cmd/check
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
post_start_check() {
|
||||||
|
echo "=== Проверка после запуска ==="
|
||||||
|
host_docker_check
|
||||||
|
echo ""
|
||||||
|
if docker compose ps 2>/dev/null | grep -qE 'shop-app|running'; then
|
||||||
|
if docker compose exec -T app wget -qO- http://127.0.0.1:8080/health 2>/dev/null; then
|
||||||
|
echo ""
|
||||||
|
echo " ✓ app /health: OK"
|
||||||
|
fi
|
||||||
|
elif command -v curl >/dev/null 2>&1; then
|
||||||
|
if curl -sf "http://127.0.0.1:${HTTP_PORT:-80}/health" 2>/dev/null; then
|
||||||
|
echo ""
|
||||||
|
echo " ✓ /health: OK"
|
||||||
|
else
|
||||||
|
echo " ✗ /health: сервис не отвечает — проверьте: docker compose ps"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
CHECK_SKIP_DB=0 CHECK_HOST_TOOLS=1 run_go_check
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$MODE" in
|
||||||
|
--after-start|post)
|
||||||
|
post_start_check
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "=== Проверка перед запуском (БД будет проверена после docker compose) ==="
|
||||||
|
host_docker_check
|
||||||
|
echo ""
|
||||||
|
CHECK_SKIP_DB=1 run_go_check
|
||||||
|
echo ""
|
||||||
|
echo "Далее: docker compose up --build -d"
|
||||||
|
echo "Затем: ./check.sh --after-start"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|||||||
+67
-23
@@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
|
||||||
@@ -15,38 +17,30 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
loadDotEnv()
|
loadDotEnv()
|
||||||
|
|
||||||
|
skipDB := os.Getenv("CHECK_SKIP_DB") == "1"
|
||||||
|
hostTools := os.Getenv("CHECK_HOST_TOOLS") != "0"
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
report := check.AppInfo()
|
report := check.AppInfo()
|
||||||
report.Items = append(report.Items, check.ToolVersions(ctx)...)
|
if hostTools {
|
||||||
|
report.Items = append(report.Items, check.ToolVersions(ctx)...)
|
||||||
|
}
|
||||||
|
|
||||||
dbURL := os.Getenv("DATABASE_URL")
|
dbURL := os.Getenv("DATABASE_URL")
|
||||||
if dbURL == "" {
|
if skipDB {
|
||||||
report.Items = append(report.Items, check.Item{
|
report.Items = append(report.Items, check.Item{
|
||||||
Name: "database",
|
Name: "database",
|
||||||
Status: check.StatusWarn,
|
Status: check.StatusWarn,
|
||||||
Detail: "DATABASE_URL не задан — запустите: go run ./cmd/install",
|
Detail: "проверка отложена — сначала выполните: docker compose up -d, затем ./check.sh --after-start",
|
||||||
|
})
|
||||||
|
} else if dbURL == "" {
|
||||||
|
report.Items = append(report.Items, check.Item{
|
||||||
|
Name: "database",
|
||||||
|
Status: check.StatusWarn,
|
||||||
|
Detail: "DATABASE_URL не задан — запустите: ./install.sh",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
pool, err := pgxpool.New(ctx, dbURL)
|
appendDBChecks(ctx, &report, dbURL)
|
||||||
if err != nil {
|
|
||||||
report.Items = append(report.Items, check.Item{
|
|
||||||
Name: "database",
|
|
||||||
Status: check.StatusError,
|
|
||||||
Detail: err.Error(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
defer pool.Close()
|
|
||||||
dbItems, err := check.Database(ctx, pool)
|
|
||||||
if err != nil {
|
|
||||||
report.Items = append(report.Items, check.Item{
|
|
||||||
Name: "database",
|
|
||||||
Status: check.StatusError,
|
|
||||||
Detail: err.Error(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
report.Items = append(report.Items, dbItems...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enc := json.NewEncoder(os.Stdout)
|
enc := json.NewEncoder(os.Stdout)
|
||||||
@@ -61,6 +55,56 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func appendDBChecks(ctx context.Context, report *check.Report, dbURL string) {
|
||||||
|
pool, err := pgxpool.New(ctx, dbURL)
|
||||||
|
if err != nil {
|
||||||
|
report.Items = append(report.Items, dbCheckItem(err, dbURL))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer pool.Close()
|
||||||
|
|
||||||
|
dbItems, err := check.Database(ctx, pool)
|
||||||
|
if err != nil {
|
||||||
|
report.Items = append(report.Items, check.Item{
|
||||||
|
Name: "database",
|
||||||
|
Status: dbCheckStatus(err, dbURL),
|
||||||
|
Detail: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
report.Items = append(report.Items, dbItems...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dbCheckItem(err error, dbURL string) check.Item {
|
||||||
|
return check.Item{
|
||||||
|
Name: "database",
|
||||||
|
Status: dbCheckStatus(err, dbURL),
|
||||||
|
Detail: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dbCheckStatus(err error, dbURL string) check.Status {
|
||||||
|
if err == nil {
|
||||||
|
return check.StatusOK
|
||||||
|
}
|
||||||
|
msg := strings.ToLower(err.Error())
|
||||||
|
if isDockerInternalHost(dbURL) && (strings.Contains(msg, "no such host") ||
|
||||||
|
strings.Contains(msg, "name or service not known") ||
|
||||||
|
strings.Contains(msg, "hostname resolving")) {
|
||||||
|
return check.StatusWarn
|
||||||
|
}
|
||||||
|
return check.StatusError
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDockerInternalHost(dbURL string) bool {
|
||||||
|
u, err := url.Parse(dbURL)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
host := u.Hostname()
|
||||||
|
return host == "postgres" || host == "db" || host == "shop-postgres"
|
||||||
|
}
|
||||||
|
|
||||||
func printSummary(r check.Report) {
|
func printSummary(r check.Report) {
|
||||||
fmt.Printf("ShopNova %s | %s\n\n", r.AppVersion, r.GoVersion)
|
fmt.Printf("ShopNova %s | %s\n\n", r.AppVersion, r.GoVersion)
|
||||||
for _, it := range r.Items {
|
for _, it := range r.Items {
|
||||||
|
|||||||
Regular → Executable
@@ -59,8 +59,9 @@ func RunInteractive(root string) (Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("\n✓ Созданы файлы: .env, caddy/Caddyfile")
|
fmt.Println("\n✓ Созданы файлы: .env, caddy/Caddyfile")
|
||||||
fmt.Println("\nДальше:")
|
fmt.Println("\nДальше (на сервере):")
|
||||||
fmt.Println(" docker compose up --build -d")
|
fmt.Println(" docker compose up --build -d")
|
||||||
|
fmt.Println(" ./check.sh --after-start")
|
||||||
if !useLocalDomain(cfg.SiteDomain) {
|
if !useLocalDomain(cfg.SiteDomain) {
|
||||||
fmt.Printf(" Сайт: https://%s\n", cfg.SiteDomain)
|
fmt.Printf(" Сайт: https://%s\n", cfg.SiteDomain)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user