Add proxy/VPN/telegram launchd and emergency runbooks; reorganize apps docs; document JA3 CrossOver runbook and Wine troubleshooting; add GOG/HoMM game scripts, disk cleanup guides, and gitea push-via-proxy helper. Ignore temp/. Co-authored-by: Cursor <cursoragent@cursor.com>
187 lines
5.6 KiB
Bash
Executable File
187 lines
5.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Универсальный запуск .exe в Whisky-bottle. См. docs/games/WINE_APPS_LAUNCH_RUNBOOK.md
|
|
set -euo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=config.sh
|
|
source "${SCRIPT_DIR}/config.sh"
|
|
|
|
BOTTLE_NAME="${WINE_BOTTLE_NAME:-}"
|
|
BOTTLE_ID="${WINE_BOTTLE_ID:-}"
|
|
GOG_BOTTLE_MODE="${GOG_BOTTLE:-0}"
|
|
PROFILE="plain"
|
|
BACKGROUND=0
|
|
LOG=""
|
|
EXE_ARG=""
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Использование: run-wine-exe.sh [опции] <exe или путь Wine>
|
|
|
|
Опции:
|
|
--bottle NAME Имя bottle в Whisky (напр. HoMM-OldenEra)
|
|
--bottle-id UUID UUID bottle (приоритет над --bottle)
|
|
--gog-bottle Bottle из scripts/games/gog/bottle.env
|
|
--profile PROF plain | steam | gog | game | ja3 (по умолчанию plain)
|
|
--background nohup, не ждать
|
|
--log FILE лог при --background
|
|
-h, --help
|
|
|
|
Примеры:
|
|
run-wine-exe.sh --profile steam 'C:\Program Files (x86)\Steam\Steam.exe'
|
|
run-wine-exe.sh --gog-bottle --profile gog ~/Downloads/setup.exe
|
|
run-wine-exe.sh --bottle HoMM-OldenEra --profile game 'C:\...\game.exe'
|
|
|
|
Документация: docs/games/WINE_APPS_LAUNCH_RUNBOOK.md
|
|
EOF
|
|
}
|
|
|
|
resolve_bottle_dir() {
|
|
if [[ "${GOG_BOTTLE_MODE}" != "1" && -z "${BOTTLE_ID}" && -z "${BOTTLE_NAME}" ]]; then
|
|
# config.sh: HoMM-OldenEra по умолчанию
|
|
return 0
|
|
fi
|
|
if [[ "${GOG_BOTTLE_MODE}" == "1" ]]; then
|
|
local gog_cfg="${SCRIPT_DIR}/gog/bottle.env"
|
|
if [[ ! -f "${gog_cfg}" ]]; then
|
|
echo "❌ Нет gog/bottle.env — bash ${SCRIPT_DIR}/gog/use-bottle.sh <UUID>"
|
|
exit 1
|
|
fi
|
|
# shellcheck source=/dev/null
|
|
source "${gog_cfg}"
|
|
BOTTLE_ID="${BOTTLE_ID:?}"
|
|
BOTTLE_NAME="${BOTTLE_NAME:-GOG-Install}"
|
|
fi
|
|
if [[ -n "${BOTTLE_ID}" ]]; then
|
|
local _f="${HOME}/Library/Containers/com.franke.Whisky/Bottles/${BOTTLE_ID}"
|
|
local _i="${HOME}/Library/Containers/com.isaacmarovitz.Whisky/Bottles/${BOTTLE_ID}"
|
|
if [[ -d "${_f}/drive_c" ]]; then
|
|
BOTTLE_DIR="${_f}"
|
|
WHISKY_LIBS="${HOME}/Library/Application Support/com.franke.Whisky"
|
|
elif [[ -d "${_i}/drive_c" ]]; then
|
|
BOTTLE_DIR="${_i}"
|
|
WHISKY_LIBS="${HOME}/Library/Application Support/com.isaacmarovitz.Whisky"
|
|
else
|
|
echo "❌ Bottle не найден: ${BOTTLE_ID}"
|
|
exit 1
|
|
fi
|
|
return 0
|
|
fi
|
|
if [[ -n "${BOTTLE_NAME}" ]]; then
|
|
local d
|
|
for d in "${HOME}/Library/Containers/com.franke.Whisky/Bottles"/* \
|
|
"${HOME}/Library/Containers/com.isaacmarovitz.Whisky/Bottles"/*; do
|
|
[[ -d "${d}/drive_c" ]] || continue
|
|
if [[ "$(basename "${d}")" == "${BOTTLE_NAME}" ]] || \
|
|
grep -q "BOTTLE_NAME=${BOTTLE_NAME}" "${d}/Metadata.plist" 2>/dev/null; then
|
|
BOTTLE_DIR="${d}"
|
|
if [[ "${d}" == *com.franke* ]]; then
|
|
WHISKY_LIBS="${HOME}/Library/Application Support/com.franke.Whisky"
|
|
else
|
|
WHISKY_LIBS="${HOME}/Library/Application Support/com.isaacmarovitz.Whisky"
|
|
fi
|
|
return 0
|
|
fi
|
|
done
|
|
echo "❌ Bottle по имени не найден: ${BOTTLE_NAME}"
|
|
exit 1
|
|
fi
|
|
# default: HoMM from config.sh (already sourced)
|
|
}
|
|
|
|
to_win_path() {
|
|
local arg="$1"
|
|
if [[ "${arg}" =~ ^[A-Za-z]:\\ ]]; then
|
|
echo "${arg}"
|
|
return 0
|
|
fi
|
|
if [[ ! -f "${arg}" ]]; then
|
|
echo "❌ Нет файла: ${arg}" >&2
|
|
exit 1
|
|
fi
|
|
local base dest
|
|
base="$(basename "${arg}")"
|
|
dest="${BOTTLE_DIR}/drive_c/${base}"
|
|
cp -f "${arg}" "${dest}"
|
|
echo "C:\\${base}"
|
|
}
|
|
|
|
apply_profile() {
|
|
case "${PROFILE}" in
|
|
plain)
|
|
export WINEPREFIX="${BOTTLE_DIR}"
|
|
export WINEMSYNC=1 WINEESYNC=1
|
|
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
|
|
unset WINEDLLOVERRIDES 2>/dev/null || true
|
|
;;
|
|
steam)
|
|
export_wine_env_steam
|
|
;;
|
|
gog)
|
|
if [[ -f "${SCRIPT_DIR}/gog/config.sh" ]]; then
|
|
# shellcheck source=/dev/null
|
|
source "${SCRIPT_DIR}/gog/config.sh"
|
|
export_wine_env_gog
|
|
else
|
|
export_wine_env_steam
|
|
export WINEDLLOVERRIDES="gdiplus=n,b"
|
|
fi
|
|
;;
|
|
game)
|
|
export_wine_env_game
|
|
;;
|
|
ja3)
|
|
if [[ -f "${SCRIPT_DIR}/gog/config.sh" ]]; then
|
|
# shellcheck source=/dev/null
|
|
source "${SCRIPT_DIR}/gog/config.sh"
|
|
export_wine_env_ja3
|
|
else
|
|
export_wine_env_game
|
|
fi
|
|
;;
|
|
*)
|
|
echo "❌ Неизвестный профиль: ${PROFILE}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
export WINEDEBUG="${WINEDEBUG:--all}"
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--bottle) BOTTLE_NAME="$2"; shift 2 ;;
|
|
--bottle-id) BOTTLE_ID="$2"; shift 2 ;;
|
|
--gog-bottle) GOG_BOTTLE_MODE=1; shift ;;
|
|
--profile) PROFILE="$2"; shift 2 ;;
|
|
--background) BACKGROUND=1; shift ;;
|
|
--log) LOG="$2"; shift 2 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
-*) echo "Неизвестная опция: $1"; usage; exit 1 ;;
|
|
*) EXE_ARG="$1"; shift ;;
|
|
esac
|
|
done
|
|
|
|
[[ -n "${EXE_ARG}" ]] || { usage; exit 1; }
|
|
|
|
resolve_bottle_dir
|
|
WINE64="${WHISKY_LIBS}/Libraries/Wine/bin/wine64"
|
|
WINE_LIB="${WHISKY_LIBS}/Libraries/Wine/lib"
|
|
[[ -x "${WINE64}" ]] || { echo "❌ Нет Wine: install-whiskywine-manual.sh"; exit 1; }
|
|
[[ -d "${BOTTLE_DIR}/drive_c" ]] || { echo "❌ Нет drive_c в ${BOTTLE_DIR}"; exit 1; }
|
|
|
|
WIN_EXE="$(to_win_path "${EXE_ARG}")"
|
|
apply_profile
|
|
|
|
echo "Bottle: ${BOTTLE_DIR##*/}"
|
|
echo "Профиль: ${PROFILE}"
|
|
echo "Запуск: ${WIN_EXE}"
|
|
|
|
if [[ "${BACKGROUND}" -eq 1 ]]; then
|
|
LOG="${LOG:-/tmp/wine-exe-$(basename "${BOTTLE_DIR}").log}"
|
|
: >"${LOG}"
|
|
nohup "${WINE64}" "${WIN_EXE}" >>"${LOG}" 2>&1 &
|
|
echo "Фон (PID $!), лог: ${LOG}"
|
|
exit 0
|
|
fi
|
|
|
|
exec "${WINE64}" "${WIN_EXE}"
|