# Script de RouterOS

Genera la instalación como un único script de RouterOS con mikroscope plan --rsc, ejecútalo desde el terminal del router o con /import, verifícalo, lee su manifiesto y retíralo.

Source: https://jmrplens.github.io/mikroscope/es/install/script/

`mikroscope plan --rsc` escribe la instalación entera como un único script de RouterOS. Ejecútalo en
el router, desde un terminal o con `/import`: sin ssh desde tu ordenador, y el script comprueba el
router antes de escribir nada. Para rellenar las opciones en un formulario, usa el
[Generador de scripts](https://jmrplens.github.io/mikroscope/es/install/generator/); escribe el mismo script.

## Generar

```sh
mikroscope plan --rsc --remote-image jmrplens/mikroscope-agent:1.6.1 --out install.rsc
```

No se conecta a nada e imprime
`install.rsc: 39 lines; review it, then paste it into the router's terminal or /import it`.
Sin `--out` el script sale por la salida estándar. Acepta las mismas opciones que `install`:
`--name`, `--veth`, `--subnet`, `--iface-list`, `--addr-list`, `--rate`, `--disk` y el resto
([CLI](https://jmrplens.github.io/mikroscope/es/reference/cli/#opciones-de-los-verbos-de-despliegue)).

- **Descarga del registro**, con `--remote-image`: el router descarga la imagen por su cuenta.
- **Tar de la imagen**, sin ella: el script espera el tar en el router como `mikroscope.tar`
  (`<name>.tar` con `--name`), y su cabecera lo dice (`BEFORE RUNNING: put the agent image tar on the device as mikroscope.tar`).
  Súbelo antes: [Instalación sin conexión](https://jmrplens.github.io/mikroscope/es/install/offline/).

Con las opciones por defecto, el script es:

```routeros
# mikroscope 1.6.1: install script for RouterOS 7.24 or later. Container name: mikroscope
# Every object it creates carries the comment "mikroscope:mikroscope (managed by mikroscope)", which is how
# `mikroscope status` and `uninstall` recognize them later. It lists them in
# mikroscope/mikroscope.manifest.txt on the router, which `mikroscope uninstall` reads and deletes last.
#
# The router pulls registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1 itself.
# The registry host is part of remote-image= (RouterOS 7.18 and later take it
# there), so this script neither reads nor changes the device-wide registry-url.
# A registry username set on the device for a registry other than registry-1.docker.io
# can make the pull end in `auth error`; `mikroscope doctor` warns about it.
#
# It runs as one block: a check that fails stops it before anything is written,
# and a step that fails stops the steps after it.

{
:if (!([/system/resource/get version] ~ "^(7[.](2[4-9]|[3-9][0-9]|[1-9][0-9][0-9])|([89]|[1-9][0-9]+)[.])")) do={ :error "mikroscope: needs RouterOS 7.24 or later" }
:if ([:len [/system/package/find name="container" disabled=no]] = 0) do={ :error "mikroscope: the container package is not installed" }
:local dm [:tostr [/system/device-mode/get container]]; :if ($dm != "yes" && $dm != "true") do={ :error "mikroscope: device-mode container is not enabled" }
:if ([:len [/interface/veth/find name="veth-mikroscope"]] > 0 && [:len [/interface/veth/find name="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"]] = 0) do={ :error "mikroscope: veth veth-mikroscope exists and is not mikroscope's" }
:if ([:len [/container/envs/find list="mikroscope-env"]] > 0 && [:len [/container/envs/find list="mikroscope-env" key="MIKROSCOPE_TAG" value="mikroscope:mikroscope (managed by mikroscope)"]] = 0) do={ :error "mikroscope: envlist mikroscope-env exists and is not mikroscope's" }
:if ([:len [/interface/list/find name="LAN"]] = 0) do={ :error "mikroscope: interface list LAN does not exist" }
:if ([:len [/file/find name="mikroscope/mikroscope.manifest.txt"]] > 0) do={ :if (!([:typeof [:find [/file/get [find name="mikroscope/mikroscope.manifest.txt"] contents] "\ntag=mikroscope:mikroscope (managed by mikroscope)\n"]] = "num")) do={ :error "mikroscope: mikroscope/mikroscope.manifest.txt exists and is not this install's manifest" } }
# install manifest mikroscope/mikroscope.manifest.txt
:local m "mikroscope-manifest=1\nname=mikroscope\ntag=mikroscope:mikroscope (managed by mikroscope)\ndisk=\nveth=veth-mikroscope\nsubnet=172.30.10.0/30\nport=9123\niface-list=LAN\naddr-list=LANs\nexpose=\ncontainer-name=\nremote-image=registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1\ntoken=no\ndir=mikroscope\nfile=mikroscope/mikroscope.manifest.txt\nobject=/interface/veth name=veth-mikroscope\nobject=/ip/address interface=veth-mikroscope\nobject=/interface/list/member interface=veth-mikroscope list=LAN\nobject=/ip/firewall/address-list list=LANs address=172.30.10.0/30\nobject=/container/envs list=mikroscope-env\nobject=/container interface=veth-mikroscope\ndir=mikroscope/mikroscope\n"; :if ([:len [/file/find name="mikroscope/mikroscope.manifest.txt"]] > 0) do={ /file/set [find name="mikroscope/mikroscope.manifest.txt"] contents=$m } else={ /file/add name="mikroscope/mikroscope.manifest.txt" contents=$m }
# veth interface veth-mikroscope
/interface/veth/add name="veth-mikroscope" address=172.30.10.2/30 gateway=172.30.10.1 comment="mikroscope:mikroscope (managed by mikroscope)"
# router address 172.30.10.1
/ip/address/add address=172.30.10.1/30 interface="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"
# interface-list membership LAN
/interface/list/member/add list="LAN" interface="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"
# address-list membership LANs
/ip/firewall/address-list/add list="LANs" address=172.30.10.0/30 comment="mikroscope:mikroscope (managed by mikroscope)"
# container mikroscope
:if ([:len [/container/envs/find list="mikroscope-env" key="MIKROSCOPE_TAG" value="mikroscope:mikroscope (managed by mikroscope)"]] > 0) do={ /container/envs/remove [find list="mikroscope-env"] }; /container/envs/add list="mikroscope-env" key=MIKROSCOPE_TAG value="mikroscope:mikroscope (managed by mikroscope)"; /container/envs/add list="mikroscope-env" key=RATE_HZ value="10"; /container/envs/add list="mikroscope-env" key=BUFFER_S value="60"; /container/envs/add list="mikroscope-env" key=PORT value="9123"; /container/envs/add list="mikroscope-env" key=ADDR value="172.30.10.2"; /container/envs/add list="mikroscope-env" key=MEM_LIMIT_MB value="16"; /container/envs/add list="mikroscope-env" key=CAPTURE_MB value="4"; /container/add remote-image="registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1" interface="veth-mikroscope" root-dir=mikroscope/mikroscope envlist="mikroscope-env" logging=yes start-on-boot=yes restart-policy=on-failure restart-max-count=5 restart-interval=10s memory-max=64M privileged=yes ignore-remote-image-change=yes comment="mikroscope:mikroscope (managed by mikroscope)"; /container/start [find comment="mikroscope:mikroscope (managed by mikroscope)"]
:local k 0; :while ([:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)" running]] = 0 && $k < 120) do={ :delay 1s; :set k ($k + 1) }
:if ([:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)" running]] > 0) do={ :put "mikroscope: agent running, http://172.30.10.2:9123/healthz" } else={ :put "mikroscope: not running yet; see /log/print where topics~\"container\"" }
}
# When it is done: /container/print where comment="mikroscope:mikroscope (managed by mikroscope)"
# The agent answers on http://172.30.10.2:9123/healthz from the router's LAN.
```

Se ejecuta como un único bloque `{ … }`, en este orden:

1. **Guardas.** Se detiene con `:error "mikroscope: …"`, antes de escribir nada, cuando la versión
   de RouterOS es anterior a 7.24, falta el paquete `container`, device mode está desactivado, una
   veth, una envlist o un contenedor `--container-name` con ese nombre son de otra cosa, la lista de
   interfaces no existe, falta el disco de `--disk`, el tar no está subido, o un fichero en la ruta
   del manifiesto no es el manifiesto de esta instalación.
2. **El manifiesto de la instalación**, y después cada objeto, con la misma etiqueta que escribe
   `install`. Un paso que falla detiene los siguientes.
3. **Una espera de hasta 120 s** a que el contenedor arranque, y después una línea: `mikroscope:
   agent running, http://172.30.10.2:9123/healthz` o `mikroscope: not running yet; see /log/print
   where topics~"container"`.

## Ejecutar en el router

- **Pegar**

  1. Abre un terminal en el router: WebFig › Terminal, Winbox › New Terminal, o ssh.
  2. Espera al prompt `] >`.
  3. Pega el fichero entero.

- **Subir e importar**

  1. Sube `install.rsc` en Files (WebFig o Winbox), o con `scp`.
  2. Ejecuta:

     ```routeros
     /import file-name=install.rsc
     ```

  3. Borra el fichero: `/file/remove install.rsc`.

> **Pega solo en el prompt**
>
> En el primer inicio de sesión RouterOS pregunta `Do you want to see the software license? [Y/n]:`,
> y las primeras líneas que pegues responden a esa pregunta y se pierden. Un pegado que pierde la
> `{` que abre el bloque se rompe. Responde a la pregunta, espera a `] >` y pega después.

Un `/import` correcto imprime:

```text
mikroscope: agent running, http://172.30.10.2:9123/healthz
Script file loaded and executed successfully
```

Una guarda que falla nombra el problema y no escribe nada, por ejemplo en la ruta del tar sin el tar
subido:

```text
Script Error: mikroscope: upload mikroscope.tar first (:error; line 20) (:import; line 1)
```

## Verificar

En el router:

```routeros
/container/print where comment="mikroscope:mikroscope (managed by mikroscope)"
:put ([/tool/fetch url="http://172.30.10.2:9123/healthz" output=user as-value]->"data")
```

La primera muestra el contenedor con la marca `R` (en marcha); la segunda imprime la respuesta de
`/healthz` del agente, `{"ok":true,…}`. Desde un ordenador con la CLI,
`mikroscope status --router …` reconoce la instalación y sondea el agente.

## Manifiesto de la instalación

El script escribe primero el manifiesto de la instalación, `mikroscope/<name>.manifest.txt` en el
disco de la instalación. Léelo en el router:

```routeros
:put [/file/get [find name="mikroscope/mikroscope.manifest.txt"] contents]
```

```text
mikroscope-manifest=1
name=mikroscope
tag=mikroscope:mikroscope (managed by mikroscope)
disk=
veth=veth-mikroscope
subnet=172.30.10.0/30
port=9123
iface-list=LAN
addr-list=LANs
expose=
container-name=
remote-image=registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1
token=no
dir=mikroscope
file=mikroscope/mikroscope.manifest.txt
object=/interface/veth name=veth-mikroscope
object=/ip/address interface=veth-mikroscope
object=/interface/list/member interface=veth-mikroscope list=LAN
object=/ip/firewall/address-list list=LANs address=172.30.10.0/30
object=/container/envs list=mikroscope-env
object=/container interface=veth-mikroscope
dir=mikroscope/mikroscope
```

Las primeras líneas son las opciones con las que se hizo la instalación, con los nombres de las
opciones de la CLI; `token=` dice solo `yes` o `no`, nunca el valor. Cada línea `object=`, `file=`
y `dir=` es algo que creó la instalación. `mikroscope uninstall` lee el manifiesto, retira todo lo
que enumera y el manifiesto al final. La ruta del tar añade `file=mikroscope.tar`.

## Limitaciones

- **No puede subir nada.** Úsalo con `--remote-image`, o sube el tar antes de ejecutarlo.
- **Con un token, el fichero es una credencial.** La línea de la envlist lleva el token en claro,
  porque el router lo necesita en claro. La CLI escribe el fichero con permisos `0600`; bórralo del
  router tras el `/import`.
- **No ejecuta `doctor`.** Las guardas cubren la versión, el paquete, device mode, las colisiones de
  nombres, la lista de interfaces, el disco, el tar y la ruta del manifiesto. No comprueban la
  memoria ni el almacenamiento libres, una ruta que se solape con la /30 ni una regla del firewall
  que descarte las respuestas del agente: ejecuta `mikroscope doctor` desde un ordenador que llegue
  al router, o repasa los [Requisitos](https://jmrplens.github.io/mikroscope/es/install/prerequisites/) a mano.

Lo que se ha ejecutado, y lo que no, está en [Probado en](https://jmrplens.github.io/mikroscope/es/about/status/#install-routes-tested).

## Retirar

Desde un ordenador con la CLI:

```sh
mikroscope uninstall --router admin@192.168.88.1 --yes
```

Lee el manifiesto, así que no necesita ninguna otra opción. Sin la CLI, ejecuta las órdenes de
retirada de [Instalación manual: terminal](https://jmrplens.github.io/mikroscope/es/install/manual-cli/#remove).
[Actualizar y desinstalar](https://jmrplens.github.io/mikroscope/es/install/upgrade/) tiene lo que la retirada nunca toca.

## Véase también

- [Generador de scripts](https://jmrplens.github.io/mikroscope/es/install/generator/): el mismo script desde un formulario en
  el navegador.
- [Instalación sin conexión](https://jmrplens.github.io/mikroscope/es/install/offline/): el tar de imagen que necesita la ruta
  del tar.
- [Salvaguardas del instalador](https://jmrplens.github.io/mikroscope/es/security/installer/#un-script-rsc-generado-es-una-credencial):
  por qué un script con token es una credencial.
- [Métodos de instalación](https://jmrplens.github.io/mikroscope/es/install/routes/): las otras formas de instalar.
