# Generador de scripts

Rellena un formulario y obtén el script de RouterOS que instala el agente, el mismo que imprime `mikroscope plan --rsc`, y el script que lo vuelve a quitar.

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

Instala el agente sin la CLI: elige las opciones, copia el script y pégalo en
el terminal del router. El script es el que imprime `mikroscope plan --rsc`
con las mismas opciones, byte a byte. Todo ocurre en esta página: nada de lo
que escribes o generas se envía a ningún sitio ni se guarda.

## Antes de empezar

- El router tiene RouterOS 7.24 o posterior, con el paquete `container` y
  `device-mode container=yes`
  ([Requisitos](https://jmrplens.github.io/mikroscope/es/install/prerequisites/)). El script comprueba
  las tres cosas primero y se detiene antes de escribir nada si falta alguna.
- Para una descarga del registro, el router llega al registro. Si no tiene
  salida, elige **Tar de la imagen subido**.
- Un firewall que descarta lo que no está en una lista necesita al agente en
  esa lista: [Listas del firewall](https://jmrplens.github.io/mikroscope/es/install/firewall/).
- En un CHR con la licencia gratuita, el router envía como mucho 1 Mbit/s, que
  una frecuencia de 50 Hz alcanza
  ([Probado en](https://jmrplens.github.io/mikroscope/es/about/status/#virtual-lab)).

## Ajustes

El formulario necesita JavaScript. El script de abajo es el predeterminado: el router descarga el agente de Docker Hub.

## Script de instalación

```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.
```

El mismo script desde la CLI:

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

**Lo que `install` escribe en tu router**

- el manifiesto de la instalación, un fichero `mikroscope/<name>.manifest.txt` en el disco de la instalación que lista las opciones y cada objeto de abajo
- una veth
- una dirección
- una pertenencia a lista de interfaces, salvo con `--iface-list none`
- una entrada de address-list, salvo con `--addr-list none`
- una envlist
- el tar de la imagen, que se borra en cuanto el contenedor está extraído, salvo que `--remote-image` haga que el router se la baje
- el contenedor, y su raíz `mikroscope/<name>` en el mismo disco

Cada objeto lleva el comentario `mikroscope:<name> (managed by mikroscope)`

`mikroscope plan` imprime cada orden antes de escribir nada.

`uninstall` elimina por etiqueta exacta más identidad, nunca por patrón, y falla nombrando el paso si queda algo.

## Subir el tar de la imagen

Solo con **Tar de la imagen subido**. Descarga el tar de la arquitectura del
router, compruébalo con las sumas de la release y cópialo al router con el
nombre que espera el script:

```sh
curl -fsSLO https://github.com/jmrplens/mikroscope/releases/download/v1.6.1/mikroscope-agent-arm64.tar
curl -fsSLO https://github.com/jmrplens/mikroscope/releases/download/v1.6.1/checksums.txt
sha256sum --ignore-missing -c checksums.txt
scp mikroscope-agent-arm64.tar admin@192.168.88.1:mikroscope.tar
```

Sin `scp`, sube el fichero en WebFig o Winbox, en **Files**, y cámbiale el
nombre a ese. El script borra el tar en cuanto RouterOS lo ha extraído.

## Ejecutar el script

1. Abre un terminal en el router: **Terminal** en WebFig, **New Terminal** en
   Winbox, o `ssh admin@192.168.88.1`.

2. Espera al prompt `] >`. En el primer inicio de sesión RouterOS pregunta si
   quieres ver la licencia del software: contesta eso antes. Un script pegado
   en la pregunta de la licencia pierde sus primeras líneas.

3. Pega el script y pulsa Intro. Espera hasta 120 s a que arranque el
   contenedor e imprime `mikroscope: agent running, http://…/healthz`, o
   `mikroscope: not running yet` y dónde mirar.

También puedes descargar el `.rsc`, subirlo en **Files** y ejecutar
`/import file-name=mikroscope-install.rsc`.

El script se ejecuta como un solo bloque. Una comprobación que falla lo detiene
antes de escribir nada, con una línea que empieza por `mikroscope:` y dice qué
falta. Un paso que falla detiene los siguientes; lo que ya creó lleva la
etiqueta, y el script de desinstalación o `mikroscope uninstall` lo quitan.

## 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")
```

Desde un ordenador de la LAN:

```sh
curl http://172.30.10.2:9123/healthz
```

La descarga desde el router imprime la respuesta de `/healthz` del agente.
`/healthz` no pide token.

## Desinstalar

Quita la instalación con la CLI, que lee el manifiesto que escribió el script y
quita cada objeto que lista, o pega el script de desinstalación, que envía las
mismas órdenes en el mismo orden. Genéralo con los ajustes con los que
instalaste.

Con la CLI:

```sh
mikroscope uninstall --router admin@192.168.88.1 --remote-image jmrplens/mikroscope-agent:1.6.1
```

Script de desinstalación:

```routeros
# mikroscope 1.6.1: uninstall script for RouterOS 7.24 or later. Container name: mikroscope
# It removes what the install script with the same settings created: every
# object tagged "mikroscope:mikroscope (managed by mikroscope)", the container root mikroscope/mikroscope,
# and mikroscope/mikroscope.manifest.txt last. It sends the commands `mikroscope uninstall` sends,
# in its order, and selects nothing by pattern.

{
# container mikroscope
:do { :local had [:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :do { /container/stop [find comment="mikroscope:mikroscope (managed by mikroscope)"] } on-error={}; :local s 0; :while (([:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)" running]] + [:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)" stopping]]) > 0 && $s < 30) do={ :delay 1s; :set s ($s + 1) }; /container/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :local i 0; :while ([:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)"]] > 0 && $i < 20) do={ :delay 1s; :set i ($i + 1) }; :if ($had > 0) do={ :local r 0; :while ([:len [/file/find name="mikroscope/mikroscope"]] > 0 && ([:len [/container/find root-dir="/mikroscope/mikroscope"]] + [:len [/container/find root-dir="mikroscope/mikroscope"]]) = 0 && $r < 10) do={ :delay 1s; :set r ($r + 1) }; :if ([:len [/file/find name="mikroscope/mikroscope"]] > 0 && ([:len [/container/find root-dir="/mikroscope/mikroscope"]] + [:len [/container/find root-dir="mikroscope/mikroscope"]]) = 0) do={ :do { /file/remove [find name="mikroscope/mikroscope"] } on-error={} } }; :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" key!="MIKROSCOPE_TAG"]; /container/envs/remove [/container/envs/find list="mikroscope-env" key="MIKROSCOPE_TAG" value="mikroscope:mikroscope (managed by mikroscope)"] } } on-error={ :put "mikroscope: could not remove container mikroscope" }
# address-list membership LANs
:do { /ip/firewall/address-list/remove [find list="LANs" address="172.30.10.0/30" comment="mikroscope:mikroscope (managed by mikroscope)"] } on-error={ :put "mikroscope: could not remove address-list membership LANs" }
# interface-list membership LAN
:do { /interface/list/member/remove [find interface="veth-mikroscope" list="LAN" comment="mikroscope:mikroscope (managed by mikroscope)"] } on-error={ :put "mikroscope: could not remove interface-list membership LAN" }
# router address 172.30.10.1
:do { /ip/address/remove [find interface="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"] } on-error={ :put "mikroscope: could not remove router address 172.30.10.1" }
# veth interface veth-mikroscope
:do { /interface/veth/remove [find name="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"] } on-error={ :put "mikroscope: could not remove veth interface veth-mikroscope" }
:do { :local n [:len [/ip/firewall/address-list/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/firewall/address-list/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/firewall/address-list " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/firewall/address-list" }
:do { :local n [:len [/interface/list/member/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /interface/list/member/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/interface/list/member " . $n) } } on-error={ :put "mikroscope: could not sweep /interface/list/member" }
:do { :local n [:len [/ip/firewall/nat/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/firewall/nat/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/firewall/nat " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/firewall/nat" }
:do { :local n [:len [/ip/firewall/filter/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/firewall/filter/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/firewall/filter " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/firewall/filter" }
:do { :local n [:len [/ip/firewall/raw/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/firewall/raw/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/firewall/raw " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/firewall/raw" }
:do { :local n [:len [/ip/firewall/mangle/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/firewall/mangle/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/firewall/mangle " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/firewall/mangle" }
:do { :local n [:len [/ip/route/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/route/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/route " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/route" }
:do { :local n [:len [/container/mounts/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /container/mounts/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/container/mounts " . $n) } } on-error={ :put "mikroscope: could not sweep /container/mounts" }
:do { :local n [:len [/ip/address/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /ip/address/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/ip/address " . $n) } } on-error={ :put "mikroscope: could not sweep /ip/address" }
:do { :local n [:len [/interface/veth/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /interface/veth/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/interface/veth " . $n) } } on-error={ :put "mikroscope: could not sweep /interface/veth" }
:do { :local n [:len [/interface/list/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /interface/list/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/interface/list " . $n) } } on-error={ :put "mikroscope: could not sweep /interface/list" }
:do { :local n [:len [/disk/find comment="mikroscope:mikroscope (managed by mikroscope)"]]; :if ($n > 0) do={ /disk/remove [find comment="mikroscope:mikroscope (managed by mikroscope)"]; :put ("@@swept=/disk " . $n) } } on-error={ :put "mikroscope: could not sweep /disk" }
# install manifest mikroscope/mikroscope.manifest.txt
:if (([:len [/ip/firewall/address-list/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/interface/list/member/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/ip/firewall/nat/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/ip/firewall/filter/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/ip/firewall/raw/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/ip/firewall/mangle/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/ip/route/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/container/mounts/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/ip/address/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/interface/veth/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/interface/list/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/disk/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)"]] + [:len [/container/envs/find list="mikroscope-env" key="MIKROSCOPE_TAG" value="mikroscope:mikroscope (managed by mikroscope)"]]) > 0) do={ :error "mikroscope: objects tagged mikroscope:mikroscope (managed by mikroscope) remain, so mikroscope/mikroscope.manifest.txt stays" }; :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={ :if ([:len [/file/find name="mikroscope/mikroscope"]] > 0 && ([:len [/container/find root-dir="/mikroscope/mikroscope"]] + [:len [/container/find root-dir="mikroscope/mikroscope"]]) = 0) do={ :do { /file/remove [find name="mikroscope/mikroscope"] } on-error={} }; /file/remove [find name="mikroscope/mikroscope.manifest.txt"] } }; :if ([:len [/file/find name~"^mikroscope/"]] = 0) do={ /file/remove [find name="mikroscope" type="directory"] }
:put "mikroscope: removed; /container/print where comment=\"mikroscope:mikroscope (managed by mikroscope)\" lists nothing"
}
```

Los dos quitan el manifiesto al final y después el directorio `mikroscope`
cuando queda vacío. Mientras quede algo etiquetado, el manifiesto se queda, así
que el siguiente intento sigue encontrando la instalación. Ninguno de los dos
toca lo que no creó la instalación: `device-mode`, el paquete `container`,
`/container/config` o un disco en RAM que añadieras tú.

## Véase también

- [Métodos de instalación](https://jmrplens.github.io/mikroscope/es/install/routes/): todas las formas
  de instalar y cuándo usar cada una.
- [Instalar con la CLI](https://jmrplens.github.io/mikroscope/es/install/): la misma instalación desde un
  ordenador, con `doctor` antes.
- [Script de RouterOS](https://jmrplens.github.io/mikroscope/es/install/script/): el mismo script desde
  `mikroscope plan --rsc`, y qué hace cada parte.
- [Instalación manual: terminal](https://jmrplens.github.io/mikroscope/es/install/manual-cli/): las
  mismas órdenes una a una, con marcadores.
- [Instalación sin conexión](https://jmrplens.github.io/mikroscope/es/install/offline/): elegir,
  descargar y verificar el tar de la imagen.
- [Almacenamiento y ajustes del contenedor](https://jmrplens.github.io/mikroscope/es/install/layout/): el disco, la
  raíz y los ajustes del contenedor.
- [Acceso por red](https://jmrplens.github.io/mikroscope/es/install/reaching-the-agent/): llegar al
  agente desde el colector.
- [Salvaguardas del instalador](https://jmrplens.github.io/mikroscope/es/security/installer/): los
  límites que pasa cada valor antes de llegar a una orden.
