Skip to Content
Tworzenie aplikacji IoTCLIZdalne maszyny przez SSH

Zdalne maszyny przez SSH

--host uruchamia polecenie ironflock na innej maszynie przez SSH zamiast na tej. Dzięki temu zarządzasz urządzeniami ze swojego laptopa, także z Maca, bez instalowania na nich ironflock. Gdy podasz tę flagę kilka razy albo użyjesz pliku hostów, polecenie działa na wielu maszynach jednocześnie.

ironflock --host [user@]machine <command> [flags] ironflock --host [user@]machine --host [user@]machine ... <command> [flags] ironflock --hosts <file> [--parallel <n>] <command> [flags]

W ten sposób na innej maszynie działa każde polecenie poza completion. --host, --hosts i --parallel to flagi globalne: mogą stać przed nazwą polecenia lub po niej.

Jedna maszyna

--host [user@]machine uruchamia to samo polecenie z tymi samymi flagami na wskazanej maszynie. To, co polecenie wypisuje, wraca bez zmian, stdout na stdout i stderr na stderr, podobnie jak jego kod wyjścia.

$ 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":[...]}

Czego potrzebuje zdalna maszyna

  • Linux na amd64, arm64 lub 32-bitowym ARM (v5 do v7). Inny system kończy się kodem wyjścia 3.
  • Serwer SSH, który wykonuje polecenia. scp ani SFTP nie są potrzebne.
  • Powłoka logowania POSIX: sh, bash, dash lub zsh. csh, tcsh i fish kończą się kodem wyjścia 3 i komunikatem, który o tym mówi.
  • Logowanie jako root albo sudo dla poleceń wymagających roota (zobacz Root na zdalnej maszynie).

Maszyna nie potrzebuje zainstalowanego ironflock: każde uruchomienie przynosi własny plik binarny.

Ustawienia SSH

--host używa ssh tej maszyny, więc twój ~/.ssh/config, klucze, agent SSH i hosty pośredniczące (jump hosts) działają tak samo jak z ssh. Wyłącza to, czego polecenie nie potrzebuje: przekazywanie agenta i X11, przekierowania portów, RemoteCommand i LocalCommand.

--host przyjmuje [user@]machine i nic więcej. Port lub inne opcje trafiają do ~/.ssh/config:

Host device-* User pi Port 2222 StrictHostKeyChecking accept-new

Wtedy ironflock --host device-17 status loguje się jako pi na porcie 2222, a ssh akceptuje klucz hosta urządzenia, którego jeszcze nie zna. Wartość --host zaczynająca się od - jest odrzucana, podobnie jak wartość zawierająca inne znaki niż litery, cyfry, ., _, - oraz : i % adresu IPv6.

Jedno połączenie SSH obsługuje całe uruchomienie, gdy ścieżka jego gniazda sterującego jest wystarczająco krótka; gniazdo powstaje w folderze tymczasowym, a w przeciwnym razie w /tmp. Wtedy ssh pyta o hasło tylko raz. W przeciwnym razie każdy krok uruchomienia otwiera własne połączenie, a ssh pyta o hasło przy każdym z nich.

Urządzenie skonfigurowane przez ironflock agent install lub IronFlockOS ma użytkownika SSH dla właściciela projektu, który loguje się kluczem z pliku .flock urządzenia. Dostęp SSH pokazuje nazwę użytkownika i sposób wyjęcia klucza z pliku.

Co dzieje się na maszynie

  1. Plik binarny. Maszyna dostaje plik binarny działający tutaj, gdy ma tę samą platformę. W przeciwnym razie ironflock pobiera plik binarny dla platformy maszyny z <download base>/cli/<os>/<arch>/<version>/ironflock i sprawdza go tutaj, zanim go użyje: jego podpis (.asc) kluczem wydań IronFlock, który zawiera ten plik binarny, oraz jego informacje o kompilacji, które muszą wskazywać program ironflock, platformę maszyny i tę samą rewizję źródeł co ten plik binarny. Pobrany plik jest przechowywany w twoim folderze pamięci podręcznej (~/.cache/ironflock w Linuksie, ~/Library/Caches/ironflock na Macu) i sprawdzany ponownie przy każdym użyciu.
  2. Folder. Plik binarny trafia do nowego folderu, który może odczytać tylko konto SSH (mktemp -d), w ${TMPDIR:-/tmp} na maszynie albo w folderze domowym konta SSH, gdy program nie może działać w folderze tymczasowym (system plików zamontowany z noexec). Gdy nie może działać w żadnym z nich, polecenie kończy się kodem wyjścia 3 i podaje oba foldery. Zanim cokolwiek uruchomi z tego folderu, maszyna sprawdza, czy folder i plik binarny należą do konta SSH i nie są dowiązaniami symbolicznymi oraz czy plik binarny ma oczekiwaną wersję i platformę.
  3. Pliki. Pliki wskazane we flagach polecenia są przesyłane razem z nim (zobacz Pliki wskazane we flagach).
  4. Polecenie. Działa z uprawnieniami konta SSH albo przez sudo (zobacz Root na zdalnej maszynie).
  5. Sprzątanie. Gdy polecenie się kończy, maszyna usuwa folder z plikiem binarnym i kopiami: także po błędzie, po utracie połączenia i po sygnałach HUP, INT, QUIT, TERM, PIPE, USR1 i USR2.

--host nie zostawia na maszynie ironflock, także po agent install. Kontynuuj stąd z --host albo zainstaluj ironflock na maszynie poleceniem instalacyjnym, które bez argumentów tylko go instaluje. self-update przez --host aktualizuje ten /usr/local/bin/ironflock na maszynie, a nie plik binarny uruchomienia (ironflock self-update).

Folder ironflock.* zostaje na maszynie w dwóch przypadkach:

  • Po utracie zasilania lub kill -9 na maszynie w trakcie działania polecenia. Folder zawiera plik binarny i kopie.
  • Gdy połączenie zostanie utracone po skopiowaniu, a przed startem polecenia, albo gdy uruchomienie zostanie przerwane tutaj w chwili, gdy krok startujący polecenie nawiązuje połączenie. Folder zawiera plik binarny, a także kopie, jeśli polecenie uruchomiono w terminalu.

Kopia pliku .flock zawiera sekret urządzenia, kopia pliku z hasłem WiFi zawiera hasło WiFi, a kopia pliku z hasłem proxy zawiera hasło proxy. Odczytać je mogą tylko konto SSH i root. Taki folder usuń ręcznie.

Pliki wskazane we flagach

FlagaPolecenia
-c, --config (plik .flock)agent install, agent configure, doctor, os flash, os install, os reset
--wifi-password-fileos flash
--proxy-password-fileagent install, agent configure, os install

Każdy plik jest odczytywany tutaj, a ścieżka względna odnosi się do bieżącego folderu roboczego tej maszyny. Plik z hasłem WiFi lub hasłem proxy może być potokiem (/dev/stdin), który jest odczytywany raz. Zawartość trafia na maszynę przez standardowe wejście połączenia SSH. Ani plik, ani jego rozmiar nie pojawiają się w wierszu poleceń, ani tutaj, ani na maszynie, gdzie każdy użytkownik może odczytać wiersze poleceń. Maszyna sprawdza każdy rozmiar względem największego, jaki przyjmuje polecenie, a potem, czy dotarła cała zawartość.

Na maszynie kopią jest <folder>/1/device.flock: we własnym folderze (tryb 0700) w folderze uruchomienia, z nazwą, jaką plik ma tutaj, i trybem 0600. Polecenie na maszynie dostaje tę ścieżkę, na przykład --config=/tmp/ironflock.k3Xf9QpL2m/1/device.flock, więc błąd dotyczący zawartości pliku wskazuje kopię.

Te sytuacje kończą polecenie na tej maszynie:

  • Kod wyjścia 1 — plik, który nie jest zwykłym plikiem (plik z hasłem WiFi lub hasłem proxy może też być potokiem), albo plik większy, niż przyjmuje polecenie: 5 MiB dla pliku .flock, 4096 bajtów dla pliku z hasłem WiFi lub hasłem proxy.
  • Kod wyjścia 2 — nazwa pliku ze znakiem sterującym.
  • Kod wyjścia 2 — --image-file i --output polecenia os flash. --host nie kopiuje obrazu na maszynę i nie przynosi z powrotem żadnego pliku. Uruchom to polecenie tutaj bez --host albo na samej maszynie. Bez --image-file maszyna sama pobiera obraz.

Root na zdalnej maszynie

  • Polecenie wymagające roota działa przez sudo, gdy konto SSH nie jest kontem root. sudo bez hasła i bez terminala działa wszędzie.
  • version, os images i os drives działają z uprawnieniami konta SSH.
  • status i doctor odczytują więcej jako root. Działają jako root, gdy konto SSH jest kontem root lub może używać sudo bez hasła i bez terminala. W przeciwnym razie działają z uprawnieniami konta SSH, bez pytania, a ich wskazówka podaje polecenie z --host root@machine.
  • agent logs czyta plik należący do roota i działa przez sudo.
  • Gdy sudo pyta o hasło albo jego konfiguracja wymaga terminala (requiretty), potrzebuje terminala na maszynie. To z kolei wymaga terminala na stdin, stdout i stderr tutaj. Bez niego polecenie kończy się kodem wyjścia 3, zanim cokolwiek zostanie skopiowane. Wtedy zaloguj się jako root, pozwól kontu SSH używać sudo bez hasła i bez terminala albo uruchom polecenie w terminalu bez przekierowań.
  • sudo, które odmawia w chwili uruchamiania polecenia, również kończy się kodem wyjścia 3.

To, co polecenie na maszynie każe uruchomić w następnej kolejności, jest poleceniem dla tej strony, bez sudo, ponieważ --host samo uzyskuje roota: ironflock --host pi@device-17 agent start.

Terminal, pytania i wyjście

  • Gdy tutaj jest terminal, polecenie dostaje terminal także na maszynie, więc może zadawać pytania. Jego stdout i stderr wracają wtedy razem, do twojego terminala.
  • Bez terminala tutaj (potok, --json do programu, CI) stdout i stderr pozostają rozdzielone, a polecenie o nic nie pyta: potwierdza --yes. To, co wypisują pliki konta SSH na maszynie, na przykład .bashrc z poleceniem echo, jest usuwane ze stdout, tak aby stdout zawierał tylko wynik polecenia.
  • --yes, --json i flagi polecenia są przekazywane dalej. Bazowy adres pobierania jest przekazywany jako --download-base: flaga albo IRONFLOCK_DL_BASE tej maszyny. Bazowy adres pobierania z danymi logowania (https://user:[email protected]/dl) kończy się kodem wyjścia 2, zanim nastąpi połączenie z jakąkolwiek maszyną, ponieważ na maszynie znalazłby się w wierszu poleceń, który może odczytać każdy jej użytkownik.
  • --help, help, grupa bez polecenia i completion są obsługiwane tutaj: to, co wypisują, jest takie samo na każdej maszynie.
  • To, co maszyna wysyła na stdout przed uruchomieniem polecenia (jej odpowiedzi i tekst z plików konta SSH), jest odczytywane do 64 KiB. Więcej kończy uruchomienie kodem wyjścia 1, zanim polecenie zacznie tam działać.

Ctrl-C i utracone połączenia

Ctrl-C tutaj dociera do polecenia na maszynie tak, jak dotarłoby Ctrl-C w jego własnym terminalu, a utracone połączenie dociera do niego jako sygnał rozłączenia, z terminalem tutaj i bez niego. Po Ctrl-C --host czeka do 15 sekund, aż maszyna poinformuje, że polecenie się zakończyło, i poda jego kod wyjścia (130, gdy zakończyło je Ctrl-C). Gdy maszyna nie zrobi tego na czas albo połączenie zakończy się wcześniej, --host kończy się kodem 130 i informuje, że polecenie może tam nadal działać. Uruchomienie, którego polecenie jeszcze nie wystartowało w chwili Ctrl-C, już go nie uruchamia.

os install przez --host ma własne zasady: gdy padnie już odpowiedź na jego pytanie, utrata połączenia go nie zatrzymuje, a polecenie czeka tutaj, aż maszyna wróci jako IronFlockOS; zobacz ironflock os install.

Kody wyjścia i błędy

Kody wyjścia to kody polecenia (Kody wyjścia). --host dodaje te:

KodZnaczenie
255ssh nie powiodło się: brak połączenia, odrzucone logowanie lub klucz hosta, zerwane połączenie
3maszyna nie może uruchomić polecenia: inny system lub procesor, powłoka logowania, która nie jest powłoką POSIX, brak folderu, w którym może działać program, sudo, które nie dopuszcza konta SSH
130przerwanie, tutaj (Ctrl-C) albo polecenia na maszynie (tamtejszy sygnał rozłączenia, przerwania lub zakończenia)

Błąd samego --host jest błędem jak każdy inny: wiersz Error: na stderr albo, z --json, obiekt błędu na stdout. Jedyny wyjątek: gdy wyjście polecenia zdążyło już dotrzeć, to wyjście jest wynikiem, a błąd to tylko wiersz Error: na stderr, także z --json.

Kilka maszyn

--host podane kilka razy albo --hosts <file> uruchamia polecenie na każdej maszynie, tak jak --host uruchamia je na jednej. Najpierw idą maszyny z --host, potem te z pliku. Plik hostów z jedną maszyną działa tak jak kilka maszyn.

$ 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)

Plik hostów

Plik wymienia po jednym [user@]machine w wierszu. # zaczyna komentarz, który biegnie do końca wiersza, a puste wiersze są pomijane. Plik może być też potokiem, na przykład --hosts <(...), i ma najwyżej 1 MiB.

# Linia pakowania 3 pi@device-17 pi@device-18 pi@device-19 # the spare unit
# Pokaż stan każdej maszyny z pliku, po 20 naraz ironflock --hosts line3.txt --parallel 20 status # Zaktualizuj agenta na każdej maszynie z pliku; agent update zadaje pytanie, więc potrzebne jest --yes ironflock --hosts line3.txt agent update --yes # Daj urządzeniom jednej lokalizacji jedno konto proxy; hasło pochodzi z pliku ironflock --hosts site-a.txt agent configure --https-proxy http://[email protected]:3128 --proxy-password-file proxy-password.txt --yes

Te sytuacje kończą się kodem wyjścia 2, zanim cokolwiek się uruchomi, a komunikat błędu podaje plik i wiersz:

  • wiersz z więcej niż jednym słowem;
  • maszyna, którą odrzuciłoby --host;
  • maszyna podana dwa razy. Dwa razy to także ta sama maszyna z dwoma użytkownikami, ponieważ polecenie działałoby na niej dwukrotnie jednocześnie. Adres i nazwa tej samej maszyny nie są rozpoznawane jako ta sama maszyna.

Uruchomienia równoległe

Jednocześnie działa najwyżej --parallel maszyn: 10 bez tej flagi, od 1 do 100. Startują w podanej kolejności, a następna startuje, gdy któraś się zakończy. --parallel bez kilku maszyn kończy się kodem wyjścia 2.

SSH bez pytań

Żadna maszyna nie dostaje terminala, a ssh o nic nie pyta (BatchMode=yes). Te sytuacje kończą się na danej maszynie kodem wyjścia 255 i komunikatem samego ssh, a pozostałe maszyny działają dalej:

  • logowanie, które wymaga hasła;
  • klucz, którego hasła nie ma w agencie SSH;
  • klucz hosta, którego ssh jeszcze nie zna.

Połącz się raz przez ssh, aby zaakceptować nowy klucz hosta, albo ustaw StrictHostKeyChecking accept-new dla tych maszyn w ~/.ssh/config, jak w przykładzie powyżej. ssh przestaje próbować połączenia po 30 sekundach (ConnectTimeout=30, niezależnie od ~/.ssh/config), więc wyłączona maszyna jest wtedy zgłaszana. sudo na maszynie, które wymaga hasła lub terminala, kończy się na tej maszynie kodem wyjścia 3; status i doctor działają wtedy z uprawnieniami konta SSH.

Wyjście kilku maszyn

  • Każdy wiersz zapisany przez maszynę przychodzi w całości, poprzedzony <host>: : jej stdout na stdout, jej stderr na stderr. Wiersze maszyn mieszają się w kolejności nadejścia.
  • Ostatni wiersz bez znaku nowego wiersza dostaje go. Wiersz dłuższy niż 64 KiB przychodzi w częściach po 64 KiB, każda poprzedzona hostem.
  • Znaki sterujące inne niż tabulator przychodzą w postaci sekwencji ucieczki (\x1b, \r), w wierszach i w podsumowaniu, tak aby żadna maszyna nie przesuwała kursora ani nie nadpisywała wiersza innej maszyny. Znak powrotu karetki na końcu wiersza jest usuwany.
  • Uruchomienie, które nie powiedzie się tutaj, dodaje swój wiersz Error: poprzedzony hostem, tak jak --host zapisuje go dla jednej maszyny.
  • Na końcu stderr dostaje podsumowanie: kod wyjścia i liczbę maszyn według sposobu zakończenia, a potem wiersz dla każdej maszyny w podanej kolejności. Wiersz podaje done albo kod wyjścia, jego rodzaj i przyczynę: błąd tutaj (dla 255 słowami samego ssh) albo wiersz Error: polecenia. Maszyna, która po Ctrl-C nie potwierdziła zakończenia polecenia, ma stan interrupted, may still run.

Kod wyjścia kilku maszyn

Polecenie kończy się najgorszym kodem wyjścia spośród maszyn: 0, gdy każda maszyna zakończyła się kodem 0. W przeciwnym razie, od najgorszego:

  1. 130 — przerwanie, tutaj lub na maszynie.
  2. 1 — polecenie nie powiodło się na maszynie, co mogło zostawić ją częściowo zmienioną, niezależnie od kodu, którym się tam zakończyło.
  3. 255 — nie udało się połączyć z maszyną albo połączenie zostało zerwane.
  4. 3 — maszyna nie była w stanie, którego wymaga polecenie, albo nie może go uruchomić.
  5. 4 — na pytanie odpowiedziano „nie”.

Kod wyjścia 2 to błędny wiersz poleceń na tej maszynie, jak przy każdym poleceniu.

Wiersze JSON

Z --json stdout dostaje jeden wiersz dla każdej maszyny, gdy jej polecenie się zakończy, w kolejności zakończenia, i nic poza tym. Program czyta wiersze w miarę ich nadchodzenia.

{"host":"pi@vm1","state":"done","exit_code":0,"result":{...}}
PoleZnaczenie
hostmaszyna tak, jak podaje ją --host lub plik hostów
statedone: polecenie zakończyło się kodem 0. failed: zakończyło się tam innym kodem albo jego uruchomienie nie powiodło się tutaj. interrupted: uruchomienie zostało przerwane, a maszyna poinformowała, że polecenie się zakończyło. may_still_run: uruchomienie zostało przerwane tutaj, a maszyna nie poinformowała w czasie oczekiwania, że polecenie się zakończyło. not_started: uruchomienie zostało przerwane, zanim przyszła kolej na maszynę; nic tam nie działało.
exit_codejak polecenie zakończyło się na maszynie albo jak jego uruchomienie zakończyło się tutaj: 255, gdy nie udało się połączyć z maszyną lub połączenie zostało zerwane, 3, gdy maszyna nie może uruchomić polecenia, 130, gdy uruchomienie zostało przerwane. Inny kod, na przykład 137 po zabiciu procesu, to kod maszyny bez zmian, ze stanem failed.
resultto, co polecenie zapisało z --json, tak jak opisuje to strona polecenia. Dla agent logs tablica jego wierszy; zachowywane jest najwyżej 16 MiB. Polecenie, które zapisuje wynik i kończy się kodem 1 (doctor, agent update), też ma to pole.
errordlaczego polecenie nie zakończyło się kodem 0, z kind i message: błąd uruchomienia tutaj (rodzaj ssh dla maszyny, z którą nie udało się połączyć, a komunikat kończy się słowami ssh w nawiasach), w przeciwnym razie obiekt błędu polecenia, a w przeciwnym razie obiekt utworzony z jego kodu wyjścia i ostatniego wiersza na stderr
outputto, co polecenie zapisało na stdout, a co nie jest JSON; albo, gdy zapisało więcej niż 16 MiB, zdanie, które o tym informuje

stderr zawiera wiersze maszyn, w tym własny wiersz Error: polecenia tam, gdzie polecenie zapisuje go z --json (agent update), oraz podsumowanie. Błędy uruchomień tutaj są tylko w wierszach na stdout.

# Maszyny, na których status nie zakończył się kodem 0 ironflock --hosts line3.txt status --json 2>/dev/null | jq -r 'select(.state != "done") | .host'

Ctrl-C na kilku maszynach

Ctrl-C, SIGTERM lub SIGHUP kończy uruchomienia tak, jak kończy uruchomienie na jednej maszynie: każde polecenie na maszynie dostaje ten sygnał, a każda maszyna ma 15 sekund na potwierdzenie, że jej polecenie się zakończyło. Maszyna, która tego nie zrobi, ma stan may_still_run. Maszyny, na które jeszcze nie przyszła kolej, niczego nie uruchamiają. Podsumowanie wymienia je jako not started, a polecenie kończy się kodem 130.

Które polecenia działają na kilku maszynach

PoleceniaNa kilku maszynach
version, status, doctor, os images, os drives, agent restart, agent startzawsze
agent logszawsze; z --follow nie z --json, ponieważ wiersz maszyny przychodzi, gdy jej polecenie się zakończy, a --follow się nie kończy
agent stop, agent update, agent configure, agent remove, os update, os rollback, self-updatez --yes: zadają pytanie, a na kilku maszynach jednocześnie nikt nie jest pytany
completionobsługiwane tutaj i na żadnej maszynie, tak jak --help
agent install, os install, os flash, os resetwcale: ich plik .flock opisuje jedno urządzenie albo wymazują dysk, nośnik lub dane urządzenia po pytaniu, które wskazuje jedną maszynę

Flaga wskazująca plik na tej maszynie jest odrzucana przy kilku maszynach, ponieważ plik trafiłby na każdą maszynę: -c poleceń doctor i agent configure opisuje jedno urządzenie. Wyjątkiem jest --proxy-password-file polecenia agent configure, dla jednego konta proxy dla maszyn jednej lokalizacji.

Wiersz poleceń, który nie działa na kilku maszynach, kończy się kodem wyjścia 2 i podaje przyczynę, zanim plik hostów zostanie odczytany i zanim nastąpi połączenie z jakąkolwiek maszyną.

Last updated on