Ho creato un semplice servizio di rete con xinetd che legge una stringa dal socket tcp ed emette la sua vista codificata. Binario originale (qrencode) che legge solo stdin.
Funziona bene quando lo uso con netcat
come echo string | nc <ip> <port>
Ma non risponde quando provo a usarlo tramite il reindirizzamento TCP bash.
exec 7<>/dev/tcp/<ip>/<port>
echo string >&7
cat <&7
Aspetta per sempre. Ho provato a fare eco a \004, cat /dev/null su questo fd e senza fortuna.
Come posso farlo funzionare?
Risposta accettata:
Quel inetd
servizio o il tuo sta probabilmente aspettando EOF prima di uscire (e quindi chiudere la connessione).
Per fare ciò, è necessario che il client spenga il lato di invio del socket mantenendo aperto il lato di ricezione. Ecco cosa nc
fa quando rileva EOF sul suo stdin.
Il /dev/tcp/host/port
interfaccia virtuale di bash
(copiato da ksh) non lo consente. Anche zsh
's ztcp
un'alternativa più flessibile non ha la capacità di chiudere asimmetricamente le connessioni.
Potresti invece fare affidamento su un timeout, ma sarebbe inaffidabile. Quindi è meglio continuare a fare affidamento su utilità dedicate come nc
o socat
(possibilmente con un coproc per avere un'interfaccia simile) o utilizzare un linguaggio di programmazione con un'API di rete adeguata (con un'interfaccia per shutdown()
).
Il carattere 0x04 (^D
) significa EOF solo per i dispositivi terminali quando la disciplina di linea è in icanon
mode (implementa un editor di linee grezze). Quindi, affinché funzioni, dovresti inserire uno pseudo-terminale tra il socket creato da xinetd
e il tuo servizio Ad esempio, avviandolo con:
socat - exec:'your-service',pty,raw,icanon,echo=0,discard=,lnext=,werase=,kill=,start=,stop=,rprnt=,erase=,fdout=3
invece di
your-service
Quindi dovresti inviare:
printf 'text\n\4' >&7
Oppure:
printf 'text\4\4' >&7
per il tuo servizio per vedere la fine dell'input.
A causa di quell'editor di riga, your-service
vedrà l'input solo quando invii newline o ^D
caratteri (abbiamo disabilitato tutti gli altri caratteri di modifica come werase
, erase
, kill
sopra e il ^C
, ^Z
… anche la gestione è disabilitata come parte di raw
).
Quindi potresti anche inserire un preprocessore di input invece che si chiude su quel carattere 0x4 come:
awk -v RS='\4' -v ORS= '{print; exit}' | your-service
(nota che awk
non può essere mawk
come mawk
insiste nel non elaborare il suo input fintanto che non ha ricevuto un buffer pieno o eof).