Vytvořil jsem jednoduchou síťovou službu s xinetd, která čte řetězec z tcp socketu a vydává jeho zakódovaný pohled. Původní binární (qrencode) právě čte stdin.
Funguje dobře, když jej používám s netcat
jako echo string | nc <ip> <port>
Ale neodpovídá, když se jej pokusím použít přes přesměrování bash tcp.
exec 7<>/dev/tcp/<ip>/<port>
echo string >&7
cat <&7
Čeká to věčně. Zkoušel jsem echo \004, cat /dev/null na toto fd a bez úspěchu.
Jak to mohu zprovoznit?
Přijatá odpověď:
To inetd
služba nebo vaše pravděpodobně čeká na EOF před ukončením (a následným uzavřením spojení).
K tomu potřebujete, aby klient vypnul odesílací stranu soketu a zároveň ponechal přijímací stranu otevřenou. To je to, co nc
dělá, když detekuje EOF na svém stdin.
/dev/tcp/host/port
virtuální rozhraní bash
(zkopírováno z ksh) to neumožňuje. Dokonce i zsh
's ztcp
flexibilnější alternativa nemá možnost asymetrického vypínání připojení.
Místo toho se můžete spolehnout na časový limit, ale to by bylo nespolehlivé. Nejlepší je tedy spoléhat na specializované nástroje jako nc
nebo socat
(možná s coproc, aby mělo podobné rozhraní), nebo použijte programovací jazyk se správným síťovým API (s rozhraním pro shutdown()
).
Znak 0x04 (^D
) znamená pouze EOF pro koncová zařízení, když je linková disciplína v icanon
režim (implementuje hrubý editor řádků). Aby to fungovalo, museli byste vložit pseudoterminál mezi zásuvku vytvořenou xinetd
a vaši službu. Například tím, že jej začnete:
socat - exec:'your-service',pty,raw,icanon,echo=0,discard=,lnext=,werase=,kill=,start=,stop=,rprnt=,erase=,fdout=3
místo
your-service
Potom budete muset odeslat:
printf 'text\n\4' >&7
Nebo:
printf 'text\4\4' >&7
aby vaše služba viděla konec vstupu.
Kvůli editoru řádků, your-service
uvidí vstup pouze při odeslání nového řádku nebo ^D
znaků (všechny ostatní úpravy znaků, jako je werase
, jsme zakázali , erase
, kill
výše a ^C
, ^Z
… manipulace je také zakázána jako součást raw
).
Takže můžete také vložit vstupní pre-procesor, který skončí na znaku 0x4 jako:
awk -v RS='\4' -v ORS= '{print; exit}' | your-service
(všimněte si, že awk
nemůže být mawk
jako mawk
trvá na tom, že nezpracuje svůj vstup, dokud neobdrží plnou vyrovnávací paměť nebo eof).