BASH - komunikace klient-server

BASH - komunikace klient-server
« kdy: 15. 02. 2022, 15:26:30 »
Ahoj, obracím se na zdejší zkušené BASHisty. Řeším následující problém.
Mám interaktivní klientskou command line aplikaci která se připojuje na server a získává z něj informace
Spojení probíhá následovně.
1. spustím aplikaci
2. zavolám "CONNECT" a aplikace se připojí na vzdálený server
3. vložím třeba "SHOW STATUS"
4. server mi vrátí výsledek
5. vložím další požadavek, případně ukončím "EXIT" a aplikace se odpojí od serveru a ukončí

Problém je, že samotný "CONNECT" je "drahý" a trvá vteřiny, než si strany vymění klíče, autorizují a ustaví spojení.
Potřebuji tedy vytvoři shellový wrapper/proxy, která spustí klientskou aplikaci, pošle mu CONNECT a bude čekat na další požadavky třeba na nějakém soketu/pipě/cokoliv. Následné příkazy jsou totiž "levné". Rád bych si vystačil s BASHem. Zkoušel jsem použít named pipy nebo nc ale prozatím nejsem úspěšný. Původní aplikace na toto není připravená. Zavolám-li ji tedy nějak takto:
echo -e "CONNECT\nSHOW STATUS" | aplikace
Aplikace to provede, vrátí mi data a ukončí se. Já se potřebuji dotazovat dynamicky a nemůžu čekat, než klient pokaždé ustaví spojení.
Dovedl by mě nekdo nasměrovat správným směrem?


Re:BASH - komunikace klient-server
« Odpověď #1 kdy: 15. 02. 2022, 16:01:55 »
Pokud to spojení je přes ssh, použíj ControlMaster a ControlPersist nastavení na straně klienta, bude se poté držet ssh spojení na pozadí a další příkaz již proběhne rychle.

Re:BASH - komunikace klient-server
« Odpověď #2 kdy: 15. 02. 2022, 16:25:05 »
Díky za snahu ale nejedná se o SSH. Používá se nějaký proprietální protokol.

Re:BASH - komunikace klient-server
« Odpověď #3 kdy: 15. 02. 2022, 16:42:07 »
Záleží na tom, jak robustní řešení chcete. Jestli ty příkazy pořád budete spouštět ručně a pohlídáte si konkurenční přístup, nebo jestli to má být součástí nějakého automatizovaného řešení. V tom druhém případě byste musel vyřešit, aby s jednou instancí aplikace v jednu chvíli komunikoval jenom jeden klient – a to podle mne nevyřešíte jen na úrovni rour, musela by tam být nějaká logika, která pozná, kdy byl jeden příkaz dokončen a může být odeslán další příkaz.

Pokud stačí ta první varianta, měly by stačit dvě pojmenované roury vytvořené přes mkfifo. Jednu napojíte na vstup vaší aplikace – co pošlete do roury, objeví se na vstupu aplikace. Druhou napojíte na výstup té aplikace a k té rouře se připojíte, když budete chtít číst výstup té aplikace. Zhruba takhle nějak:

Kód: [Vybrat]
mkfifo app_in
mkfifo app_out
aplikace < app_in > app_out
echo -e 'CONNECT\n' > app_in
cat < app_out
echo -e 'SHOW STATUS\n' > app_in
cat < app_out
Ten výpis výstupu samozřejmě budete vždy muset přerušit, když budete mít pocit, že už se vypsalo všechno.

Re:BASH - komunikace klient-server
« Odpověď #4 kdy: 15. 02. 2022, 17:11:23 »
a můžeš lépe popsat jak vlastně s tou aplikací z bashe komunikuješ? Jak si přebírá vstup, jak si odebíráš výstup a o jaké datové formáty se jedná?

Pokud jí můžeš předat vstup ze stdin a výstup ti stačí na stdout, můžeš to udělat takhle
Kód: [Vybrat]
touch commands
./connect.sh & < <(tail -f commands)
echo "SHOW STATUS" >> commands
echo "SHOW STATUS2" >> commands
# ukončí connect.sh
kill %1

To je jen nástřel, třeba se chytneš. Řešit tohle v bashi bude ale i tak utrpení.


AM

Re:BASH - komunikace klient-server
« Odpověď #5 kdy: 16. 02. 2022, 11:35:52 »
Kdysi dávno se pro tyto účely používal Korn shell, protože umí obousměrné roury (two-way pipes), viz např. https://docstore.mik.ua/orelly/unix3/korn/ch08_05.htm . Korn shell se ale už moc nevyvíjí, a tak ho některé distribuce ani neobsahují. V nových verzích Bashe se to prý dá udělat přes coproc, viz. https://unix.stackexchange.com/questions/53641/how-to-make-bidirectional-pipe-between-two-programs . Na té stránce jsou i jiná řešení.

AgentK

  • ***
  • 128
  • Evolve or die!
    • Zobrazit profil
    • E-mail
Re:BASH - komunikace klient-server
« Odpověď #6 kdy: 16. 02. 2022, 11:53:55 »
pokud je to terminalova aplikace, treba to pujde pres `expect`

Re:BASH - komunikace klient-server
« Odpověď #7 kdy: 16. 02. 2022, 13:32:40 »
Díky všem za tipy. Jste skvělý  :)
Ještě se do toho ponořím a vrátím se (snad) s výsledkem.

_Jenda

  • *****
  • 1 095
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:BASH - komunikace klient-server
« Odpověď #8 kdy: 16. 02. 2022, 23:39:28 »
Ano, obecně se na to používá expect, ale já se nechci učit další jazyk, takže na to používám Python.

p = subprocess.Popen("./connect.sh", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("CONNECT")
ret = p.stdout.readline()
p.stdin.write("SHOW STATUS")
ret = p.stdout.readline()

atd. (psáno po paměti, tak s rezervou)

Možná by se to hodilo dělat asynchronně, tj. čtení v jiném threadu a třeba to cpát do https://docs.python.org/3/library/queue.html.

AgentK

  • ***
  • 128
  • Evolve or die!
    • Zobrazit profil
    • E-mail
Re:BASH - komunikace klient-server
« Odpověď #9 kdy: 17. 02. 2022, 07:26:14 »
Ano, obecně se na to používá expect, ale já se nechci učit další jazyk, takže na to používám Python.
...

Je možný použít i pexpect...

Když se to dělá ručně, tak se člověk nevyhne řešení všemožných různých stavů a nakonec se trochu vstupní časové investice do (p)expectu vyplatí. Kdyby to bylo SSH, tak bych váhal a třeba spíš doporučil paramiko.

Samozřejmě proti gustu nic, ale proč si ztěžovat situaci když přesně pro můj problém existují dospělé nástroje?