Máquinas remotas por SSH
--host ejecuta un comando ironflock en otra máquina por SSH en lugar de en esta. Lo usas para gestionar dispositivos desde tu portátil, incluido un Mac, sin instalar ironflock en ellos. Indicado más de una vez, o con un archivo de hosts, ejecuta el comando en muchas máquinas a la vez.
ironflock --host [user@]machine <command> [flags]
ironflock --host [user@]machine --host [user@]machine ... <command> [flags]
ironflock --hosts <file> [--parallel <n>] <command> [flags]Todos los comandos salvo completion se ejecutan así en otra máquina. --host, --hosts y --parallel son flags globales: pueden ir antes o después del nombre del comando.
Una máquina
--host [user@]machine ejecuta el mismo comando con los mismos flags en esa máquina. Lo que imprime vuelve tal cual, stdout a stdout y stderr a stderr, y lo mismo ocurre con su código de salida.
$ ironflock --host pi@device-17 version
ironflock 2.0.2 linux/arm64
$ ironflock --host pi@device-17 agent remove --yes --json 2>/dev/null
{"action":"removed","removed":[...]}Qué necesita la otra máquina
- Linux en amd64, arm64 o ARM de 32 bits (v5 a v7). Otro sistema termina con el código de salida 3.
- Un servidor SSH que ejecute comandos. No hace falta
scpni SFTP. - Un shell de inicio de sesión POSIX: sh, bash, dash o zsh. csh, tcsh y fish terminan con el código de salida 3 y un mensaje que lo indica.
- Acceso como root, o
sudo, para los comandos que necesitan root (consulta Root en la otra máquina).
La máquina no necesita tener ironflock instalado: cada ejecución lleva su propio binario.
Ajustes de SSH
--host usa el ssh de esta máquina, así que tu ~/.ssh/config, tus claves, el agente SSH y los jump hosts funcionan como con ssh. Desactiva lo que el comando no necesita: el reenvío del agente y de X11, los reenvíos de puertos, un RemoteCommand y un LocalCommand.
--host acepta [user@]machine y nada más. Un puerto u otras opciones van en ~/.ssh/config:
Host device-*
User pi
Port 2222
StrictHostKeyChecking accept-newCon esto, ironflock --host device-17 status inicia sesión como pi en el puerto 2222, y ssh acepta la clave de host de un dispositivo que aún no conoce. Se rechaza un valor de --host que empieza por -, y también uno con caracteres distintos de letras, dígitos, ., _, - y los : y % de una dirección IPv6.
Una sola conexión SSH sirve para toda la ejecución cuando la ruta de su socket de control es lo bastante corta; el socket se crea en la carpeta temporal o, si no, en /tmp. Entonces ssh pide la contraseña una sola vez. Si no, cada paso de la ejecución abre su propia conexión, y ssh la pide de nuevo en cada uno.
Un dispositivo que configuró ironflock agent install o IronFlockOS tiene un usuario SSH para el propietario del proyecto, que inicia sesión con la clave del archivo .flock del dispositivo. Acceso SSH muestra el nombre de usuario y cómo extraer la clave del archivo.
Qué ocurre en la máquina
- El binario. La máquina recibe el binario que se ejecuta aquí cuando tiene la misma plataforma. Si no,
ironflockdescarga el binario para la plataforma de la máquina desde<download base>/cli/<os>/<arch>/<version>/ironflocky lo comprueba aquí antes de usarlo: su firma (.asc) con la clave de release de IronFlock que lleva este binario, y su información de compilación, que tiene que indicar el programaironflock, la plataforma de la máquina y la misma revisión del código fuente que este binario. La descarga se guarda en tu carpeta de caché (~/.cache/ironflocken Linux,~/Library/Caches/ironflocken un Mac) y se vuelve a comprobar en cada uso. - La carpeta. El binario va a una carpeta nueva que solo puede leer la cuenta de acceso (
mktemp -d), bajo${TMPDIR:-/tmp}en la máquina, o bajo el directorio personal de la cuenta de acceso cuando un programa no puede ejecutarse en la carpeta temporal (un sistema de archivos montado connoexec). Cuando no puede ejecutarse en ninguna de las dos, el comando termina con el código de salida 3 e indica ambas. Antes de ejecutar nada de la carpeta, la máquina comprueba que la carpeta y el binario pertenecen a la cuenta de acceso y no son enlaces simbólicos, y que el binario es de la versión y la plataforma esperadas. - Los archivos. Los archivos indicados en los flags del comando se envían también (consulta Archivos indicados en flags).
- El comando. Se ejecuta como la cuenta de acceso, o mediante
sudo(consulta Root en la otra máquina). - La limpieza. Cuando el comando termina, la máquina elimina la carpeta con el binario y las copias: también tras un fallo, tras una conexión perdida y tras las señales HUP, INT, QUIT, TERM, PIPE, USR1 y USR2.
--host no deja ningún ironflock en la máquina, tampoco después de agent install. Sigue con --host a partir de ahí, o instala ironflock en la máquina con la línea de instalación, que sin argumentos solo lo instala. self-update con --host actualiza ese /usr/local/bin/ironflock de la máquina, no el binario de la ejecución (ironflock self-update).
Una carpeta ironflock.* queda en la máquina en dos casos:
- Tras un corte de corriente o un
kill -9en la máquina mientras se ejecuta el comando. La carpeta contiene el binario y las copias. - Cuando la conexión se pierde después de la copia y antes de que empiece el comando, o la ejecución se interrumpe aquí mientras se conecta el paso que inicia el comando. La carpeta contiene el binario y, si ejecutaste el comando en una terminal, también las copias.
La copia de un archivo .flock contiene el secreto del dispositivo; la copia de un archivo de frase de contraseña, la frase de contraseña del WiFi; la copia de un archivo de contraseña, la contraseña del proxy. Solo pueden leerlas la cuenta de acceso y root. Elimina a mano una carpeta así.
Archivos indicados en flags
| Flag | Comandos |
|---|---|
-c, --config (el archivo .flock) | agent install, agent configure, doctor, os flash, os install, os reset |
--wifi-password-file | os flash |
--proxy-password-file | agent install, agent configure, os install |
Cada archivo se lee aquí, y una ruta relativa es relativa a la carpeta de trabajo de esta máquina. Un archivo de frase de contraseña o de contraseña puede ser una tubería (/dev/stdin), que se lee una vez. El contenido llega a la máquina por la entrada estándar de la conexión SSH. Ni el archivo ni su tamaño aparecen en una línea de comandos, ni aquí ni en la máquina, donde cualquier usuario puede leer las líneas de comandos. La máquina comprueba cada tamaño con el máximo que admite el comando y, después, que haya llegado todo.
En la máquina, la copia es <folder>/1/device.flock: en una carpeta propia (modo 0700) dentro de la carpeta de la ejecución, con el nombre que tiene aquí y modo 0600. El comando de allí recibe esa ruta, por ejemplo --config=/tmp/ironflock.k3Xf9QpL2m/1/device.flock, de modo que un error sobre el contenido del archivo indica la copia.
Estos casos terminan el comando en esta máquina:
- Código de salida 1 — un archivo que no es un archivo normal (un archivo de frase de contraseña o de contraseña también puede ser una tubería), o uno mayor de lo que admite el comando: 5 MiB para un archivo
.flock, 4096 bytes para un archivo de frase de contraseña o de contraseña. - Código de salida 2 — un nombre de archivo con un carácter de control.
- Código de salida 2 —
--image-filey--outputdeos flash.--hostno copia ninguna imagen a la máquina ni trae ningún archivo de vuelta. Ejecuta ese comando aquí sin--host, o en la propia máquina. Sin--image-file, la máquina descarga la imagen por sí misma.
Root en la otra máquina
- Un comando que necesita root se ejecuta mediante
sudocuando la cuenta de acceso no es root.sudosin contraseña y sin terminal funciona en cualquier situación. version,os imagesyos drivesse ejecutan como la cuenta de acceso.statusydoctorleen más con root. Se ejecutan como root cuando la cuenta de acceso es root o puede usarsudosin contraseña y sin terminal. Si no, se ejecutan como la cuenta de acceso, sin preguntar, y su sugerencia indica el comando con--host root@machine.agent logslee un archivo de root y se ejecuta mediantesudo.- Cuando
sudopide una contraseña, o su configuración exige una terminal (requiretty), necesita una terminal en la máquina. Eso requiere una terminal en stdin, stdout y stderr aquí. Sin ella, el comando termina con el código de salida 3 antes de copiar nada. En ese caso, inicia sesión como root, permite que la cuenta de acceso usesudosin contraseña y sin terminal, o ejecuta el comando en una terminal sin redirección. - Un
sudoque se niega cuando el comando está a punto de ejecutarse también termina con el código de salida 3.
Lo que el comando de allí indique ejecutar a continuación es un comando para este lado, sin sudo, ya que --host obtiene root por sí mismo: ironflock --host pi@device-17 agent start.
Terminal, preguntas y salida
- Con una terminal aquí, el comando también recibe una en la máquina, para que pueda hacer sus preguntas. Su stdout y su stderr vuelven entonces juntos, a tu terminal.
- Sin terminal aquí (una tubería,
--jsonhacia un programa, CI), stdout y stderr se mantienen separados, y el comando no pregunta nada:--yesconfirma. Lo que imprimen los archivos de la cuenta de acceso en la máquina, como un.bashrcque muestra texto, se descarta de stdout, para que stdout lleve solo el resultado del comando. --yes,--jsony los flags del comando se transmiten. La base de descarga se transmite como--download-base: el flag o elIRONFLOCK_DL_BASEde esta máquina. Una base de descarga con credenciales (https://user:[email protected]/dl) termina con el código de salida 2 antes de llegar a ninguna máquina, ya que en la máquina quedaría en una línea de comandos que cualquier usuario de allí puede leer.--help,help, un grupo sin comando ycompletionse responden aquí: lo que imprimen es igual en todas las máquinas.- Lo que la máquina envía a stdout antes de que se ejecute el comando (sus respuestas y el texto de los archivos de la cuenta de acceso) se lee hasta 64 KiB. Si hay más, la ejecución termina con el código de salida 1 antes de que el comando se ejecute allí.
Ctrl-C y conexiones perdidas
Ctrl-C aquí llega al comando de allí como llegaría Ctrl-C en su propia terminal, y una conexión perdida le llega como una desconexión (SIGHUP), con o sin terminal aquí. Tras Ctrl-C, --host espera hasta 15 segundos a que la máquina diga que el comando de allí terminó, con su código de salida (130 si lo terminó Ctrl-C). Si la máquina no lo dice a tiempo, o la conexión termina antes, --host termina con 130 e indica que el comando puede seguir ejecutándose allí. Una ejecución cuyo comando no había empezado cuando llegó Ctrl-C ya no lo inicia.
os install con --host tiene sus propias reglas: una vez respondida su pregunta, una conexión perdida ya no lo detiene, y el comando espera aquí a que la máquina vuelva como IronFlockOS; consulta ironflock os install.
Códigos de salida y errores
Los códigos de salida son los del comando (Códigos de salida). --host añade estos:
| Código | Significado |
|---|---|
| 255 | ssh falló: no hay conexión, se rechazó la cuenta de acceso o la clave de host, una conexión que se cortó |
| 3 | la máquina no puede ejecutar el comando: otro sistema u otra CPU, un shell de inicio de sesión que no es un shell POSIX, ninguna carpeta donde pueda ejecutarse un programa, un sudo que no lo permite a la cuenta de acceso |
| 130 | una interrupción, aquí (Ctrl-C) o del comando en la máquina (una desconexión, una interrupción o una señal de terminación allí) |
Un fallo del propio --host es un error como cualquier otro: una línea Error: en stderr o, con --json, el objeto de error en stdout. La única excepción: cuando la salida del comando ya había llegado, esa salida es el resultado, y el error es solo la línea Error: en stderr, también con --json.
Varias máquinas
--host indicado más de una vez, o --hosts <file>, ejecuta el comando en cada máquina, igual que --host lo ejecuta en una. Primero van las máquinas de --host, después las del archivo. Un archivo de hosts con una sola máquina se ejecuta igual que con varias.
$ ironflock --host pi@vm1 --host pi@vm2 --host pi@vm3 status
pi@vm2: Agent: installed in /opt/ironflock/device-agent
pi@vm2: Version: 1.6.9
pi@vm2: Service: running (ironflock-device-agent.service)
pi@vm3: ssh: connect to host vm3 port 22: Connection timed out
pi@vm3: Error: the SSH connection to pi@vm3 failed
pi@vm1: Agent: installed in /opt/ironflock/device-agent
...
Summary of "status" on 3 machines, exit code 255: 2 done, 1 ssh.
pi@vm1 done
pi@vm2 done
pi@vm3 255 ssh: the SSH connection to pi@vm3 failed (ssh: connect to host vm3 port 22: Connection timed out)El archivo de hosts
El archivo indica una [user@]machine por línea. Un # inicia un comentario, que llega hasta el final de la línea, y las líneas vacías se omiten. El archivo también puede ser una tubería, como --hosts <(...), y ocupa como máximo 1 MiB.
# Línea de envasado 3
pi@device-17
pi@device-18
pi@device-19 # the spare unit# Mostrar el estado de cada máquina del archivo, 20 a la vez
ironflock --hosts line3.txt --parallel 20 status
# Actualizar el agente en cada máquina del archivo; agent update pregunta, así que hace falta --yes
ironflock --hosts line3.txt agent update --yes
# Dar a los dispositivos de un emplazamiento una única cuenta de proxy; la contraseña viene de un archivo
ironflock --hosts site-a.txt agent configure --https-proxy http://[email protected]:3128 --proxy-password-file proxy-password.txt --yesEstos casos terminan con el código de salida 2 antes de que se ejecute nada, y el error indica el archivo y la línea:
- una línea con más de una palabra;
- una máquina que
--hostrechazaría; - una máquina indicada dos veces. También cuenta como dos veces la misma máquina con dos usuarios, ya que el comando se ejecutaría en ella dos veces a la vez. Una dirección y un nombre de la misma máquina no se reconocen como la misma.
Ejecuciones en paralelo
Como máximo se ejecutan a la vez --parallel máquinas: 10 sin el flag, de 1 a 100. Empiezan en el orden indicado, y la siguiente empieza cuando termina una. --parallel sin varias máquinas termina con el código de salida 2.
SSH sin preguntas
Ninguna máquina recibe una terminal, y ssh no pregunta nada (BatchMode=yes). Estos casos fallan en esa máquina con el código de salida 255 y el mensaje del propio ssh, y las demás máquinas siguen:
- una cuenta de acceso que pide contraseña;
- una clave cuya frase de contraseña no está en el agente SSH;
- una clave de host que
sshaún no conoce.
Conéctate una vez con ssh para aceptar una clave de host nueva, o define StrictHostKeyChecking accept-new para esas máquinas en ~/.ssh/config, como en el ejemplo anterior. ssh deja de intentar conectarse tras 30 segundos (ConnectTimeout=30, diga lo que diga ~/.ssh/config), así que una máquina apagada se notifica entonces. Un sudo allí que pide contraseña o terminal termina con el código de salida 3 en esa máquina; status y doctor se ejecutan entonces como la cuenta de acceso.
Salida de varias máquinas
- Cada línea que escribe una máquina llega entera, con
<host>:delante: su stdout en stdout, su stderr en stderr. Las líneas de las máquinas se mezclan en el orden en que llegan. - Una última línea sin salto de línea recibe uno. Una línea de más de 64 KiB llega en partes de 64 KiB, cada una con el host delante.
- Los caracteres de control distintos del tabulador llegan escapados (
\x1b,\r), en las líneas y en el resumen, para que ninguna máquina mueva el cursor ni sobrescriba la línea de otra máquina. Un retorno de carro al final de una línea se elimina. - Una ejecución que falla aquí añade su línea
Error:con el host delante, igual que la escribe--hostpara una sola máquina. - Al final, stderr recibe un resumen: el código de salida y cuántas máquinas terminaron de cada forma, y después una línea por máquina en el orden indicado. La línea dice
done, o el código de salida, su tipo y el motivo: el error de aquí (para 255, con el mensaje del propiossh) o la líneaError:del comando. Una máquina que no confirmó el final de su comando tras Ctrl-C aparece comointerrupted, may still run.
Código de salida de varias máquinas
El comando termina con el peor código de salida de las máquinas: 0 si todas las máquinas terminaron con 0. Si no, empezando por el peor:
- 130 — interrumpido, aquí o en una máquina.
- 1 — el comando falló en una máquina, que puede haber quedado cambiada a medias, sea cual sea el código con el que terminó allí.
- 255 — no se alcanzó una máquina, o la conexión se cortó.
- 3 — una máquina no estaba en el estado que necesita el comando, o no puede ejecutarlo.
- 4 — se respondió no a una pregunta.
El código de salida 2 es una línea de comandos incorrecta aquí, como en todos los comandos.
Líneas JSON
Con --json, stdout recibe una línea por cada máquina cuando su comando ha terminado, en el orden en que terminan, y nada más. Un programa lee las líneas a medida que llegan.
{"host":"pi@vm1","state":"done","exit_code":0,"result":{...}}| Campo | Significado |
|---|---|
host | la máquina tal como la indican --host o el archivo de hosts |
state | done: el comando terminó con 0. failed: terminó allí con otro código, o su ejecución falló aquí. interrupted: la ejecución se interrumpió y la máquina dijo que el comando terminó. may_still_run: la ejecución se interrumpió aquí y la máquina no dijo dentro del tiempo de espera que el comando terminó. not_started: la ejecución se interrumpió antes de que llegara el turno de la máquina; allí no se ejecutó nada. |
exit_code | cómo terminó el comando en la máquina, o cómo terminó su ejecución aquí: 255 si no se alcanzó la máquina o la conexión se cortó, 3 si la máquina no puede ejecutar el comando, 130 si la ejecución se interrumpió. Cualquier otro código, como 137 tras un kill, es el de la máquina tal cual, con el estado failed. |
result | lo que el comando escribió con --json, como lo describe la página del comando. Para agent logs, el array de sus líneas; se conservan como máximo 16 MiB. Un comando que escribe su resultado y termina con 1 (doctor, agent update) también lo tiene. |
error | por qué el comando no terminó con 0, con kind y message: el error de la ejecución aquí (tipo ssh para una máquina que no se alcanzó, con el mensaje terminado en las palabras de ssh entre paréntesis); si no, el objeto de error del comando; si no, uno formado con su código de salida y su última línea en stderr |
output | lo que el comando escribió en stdout que no es JSON; o, si escribió más de 16 MiB, una frase que lo indica |
stderr contiene las líneas de las máquinas, entre ellas la propia línea Error: de un comando cuando escribe una con --json (agent update), y el resumen. Los errores de las ejecuciones aquí están solo en las líneas de stdout.
# Las máquinas en las que status no terminó con 0
ironflock --hosts line3.txt status --json 2>/dev/null | jq -r 'select(.state != "done") | .host'Ctrl-C en varias máquinas
Ctrl-C, SIGTERM o SIGHUP terminan las ejecuciones igual que terminan una ejecución en una máquina: cada comando de allí lo recibe, y cada máquina tiene 15 segundos para confirmar que su comando terminó. Una máquina que no lo confirma queda como may_still_run. Las máquinas cuyo turno no ha llegado no ejecutan nada. El resumen las enumera como not started, y el comando termina con 130.
Qué comandos se ejecutan en varias máquinas
| Comandos | En varias máquinas |
|---|---|
version, status, doctor, os images, os drives, agent restart, agent start | siempre |
agent logs | siempre; con --follow, no con --json, ya que la línea de una máquina llega cuando termina su comando, y --follow no termina |
agent stop, agent update, agent configure, agent remove, os update, os rollback, self-update | con --yes: preguntan, y en varias máquinas a la vez no se pregunta a nadie |
completion | se responde aquí y en ninguna máquina, igual que --help |
agent install, os install, os flash, os reset | nunca: su archivo .flock indica un único dispositivo, o borran un disco, una unidad o los datos de un dispositivo tras una pregunta que nombra esa única máquina |
Con varias máquinas se rechaza un flag que indica un archivo de esta máquina, ya que el archivo iría a todas las máquinas: -c de doctor y de agent configure indica un único dispositivo. La excepción es --proxy-password-file de agent configure, para una única cuenta de proxy para las máquinas de un emplazamiento.
Una línea de comandos que no se ejecuta en varias máquinas termina con el código de salida 2 e indica por qué, antes de leer el archivo de hosts y antes de llegar a ninguna máquina.