#!/bin/sh # Instalador de Agencia para Linux y macOS. # # curl -fsSL https://get.agencia.ip1.cc/install.sh | sh # curl -fsSL https://get.agencia.ip1.cc/install.sh | sh -s -- --no-gui # argumentos para setup # # Baja el paquete de este OS y arquitectura, verifica su SHA-256, lo descomprime en una # carpeta temporal y le pasa la posta a `agencia setup`, que es el que instala de verdad # (carpeta de la app, servicio, PATH). Este script no escribe nada fuera del temporal. # # Variables: # AGENCIA_VERSION instalar esta versión (v0.1.0) en vez de la última # AGENCIA_GET_URL de dónde bajar (default https://get.agencia.ip1.cc); para probar # contra un server local # AGENCIA_SKIP_SETUP 1 = bajar, verificar y descomprimir, pero en vez de correr setup # imprimir lo que iba a correr # # POSIX sh y no bash: en Debian y Ubuntu `sh` es dash, y es lo que corre `curl | sh`. # # Todo está adentro de main(), que se llama en la última línea. Con `curl | sh` el shell # ejecuta a medida que llega el texto: si la conexión se corta a la mitad, sin la función # correría medio script. Así, o llegó entero, o no corre nada. set -eu say() { printf '%s\n' "$*"; } err() { printf 'agencia: %s\n' "$*" >&2; } die() { err "$*"; exit 1; } # fetch URL ARCHIVO, con curl o con wget: un macOS trae curl y un Debian mínimo a veces # sólo wget. fetch() { if command -v curl >/dev/null 2>&1; then curl -fsSL --retry 3 -o "$2" "$1" elif command -v wget >/dev/null 2>&1; then wget -q -O "$2" "$1" else die "hace falta curl o wget para bajar Agencia." fi } sha256_of() { if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | awk '{print $1}' elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}' else die "hace falta sha256sum o shasum para verificar la descarga." fi } detect_os() { case "$(uname -s)" in Linux) echo linux ;; Darwin) echo darwin ;; MINGW* | MSYS* | CYGWIN*) die "en Windows usá PowerShell: irm https://get.agencia.ip1.cc/install.ps1 | iex" ;; *) die "no hay paquete de Agencia para $(uname -s)." ;; esac } detect_arch() { arch="$(uname -m)" case "$arch" in x86_64 | amd64) arch=amd64 ;; aarch64 | arm64) arch=arm64 ;; *) die "no hay paquete de Agencia para la arquitectura $arch." ;; esac # Una terminal abierta con Rosetta en un Mac con Apple Silicon dice x86_64. El # paquete de amd64 andaría emulado, pero el nativo es el que corresponde. if [ "$1" = darwin ] && [ "$arch" = amd64 ] && [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)" = 1 ]; then arch=arm64 fi echo "$arch" } main() { base="${AGENCIA_GET_URL:-https://get.agencia.ip1.cc}" base="${base%/}" os="$(detect_os)" arch="$(detect_arch "$os")" tmp="$(mktemp -d 2>/dev/null || mktemp -d -t agencia)" # Se borra al salir, también con Ctrl+C. setup copia la app a su lugar definitivo, # así que nada de lo que quede acá hace falta después. trap 'rm -rf "$tmp"' EXIT trap 'exit 130' INT TERM version="${AGENCIA_VERSION:-}" if [ -z "$version" ]; then fetch "$base/latest.json" "$tmp/latest.json" || die "no pude bajar $base/latest.json. ¿Hay conexión?" # latest.json lo escribe release.sh con una clave por línea: alcanza con sed y # evita depender de jq o python, que una máquina recién instalada no tiene. version="$(sed -n 's/^ *"version" *: *"\([^"]*\)".*/\1/p' "$tmp/latest.json" | head -n 1)" [ -n "$version" ] || die "el latest.json de $base no dice qué versión es la última." fi case "$version" in v*) ;; *) version="v$version" ;; esac file="agencia-$version-$os-$arch.tar.gz" rel="$base/releases/$version" say "Bajando Agencia $version para $os/$arch..." fetch "$rel/SHA256SUMS" "$tmp/SHA256SUMS" || die "no encontré la versión $version en $base." fetch "$rel/$file" "$tmp/$file" || die "no pude bajar $rel/$file." want="$(awk -v f="$file" '$2 == f || $2 == "*" f {print $1}' "$tmp/SHA256SUMS")" [ -n "$want" ] || die "SHA256SUMS no tiene el hash de $file." got="$(sha256_of "$tmp/$file")" if [ "$got" != "$want" ]; then err "el SHA-256 de la descarga no coincide con el publicado." err " esperado: $want" err " bajado: $got" die "no instalo un archivo que no es el que se publicó. Probá de nuevo en un rato." fi say "SHA-256 verificado." tar -xzf "$tmp/$file" -C "$tmp" app="$tmp/agencia/agencia" [ -x "$app" ] || die "el paquete no trae el binario de agencia." if [ "${AGENCIA_SKIP_SETUP:-}" = 1 ]; then say "AGENCIA_SKIP_SETUP=1: no corro setup. Iba a correr:" say " $app setup $*" "$app" version return 0 fi # Con `curl | sh` la entrada del script es el pipe, no el teclado: setup no podría # preguntar nada. /dev/tty es la terminal de quien lo corrió. Se prueba abrirla y no # sólo que exista, porque en un contenedor o en CI existe y falla al abrirse; ahí # setup sigue con la entrada que haya y sus defaults. say "Arrancando el instalador..." say status=0 if [ ! -t 0 ] && (exec /dev/null; then "$app" setup "$@"