mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f
I am new to bash, I am trying to understand this piece of "code".
- Why a while loop is not needed? How can this work? Is it itself a loop? Why? How?
Also,
cat filePipe
by itself ONLY PRINTS ONE LINE, and then exits (I just tested it), and to make cat not to exit I do:while cat pipeFile ; do : ; done
. So how does that above work? - I don't get the order of execution... at the beginning /tmp/f is empty, so cat /tmp/f should "send" an empty stream to /bin/bash which just send it to nc which opens a connection and "sends" the interactive bash to whoever connects... and the response of the client is sent to /tmp/f ... and then? What? How can it can go back and do the same things again?
CodePudding user response:
/tmp/f is NOT empty, but a fifo, a bi-directional link.
Someone connects to port 1234, type something, which nc
will forward to fifo
which then feeds into bash
.
bash
runs the command and sends results back to nc
.
CodePudding user response:
When bash
parses the line mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f
, several things happen. First, the fifo is created. Then, in no particular order, 3 things happen: cat
is started, bash
is started and nc
is started with its output stream connected to /tmp/f
. cat
is now going to block until some other process opens /tmp/f
for writing; the nc
is about to do that (or already did it, but we don't know if cat
will start before nc
or if nc
starts before cat
, nor do we know in which order they will open the fifo, but whoever does it first will block until the other completes the operation). Once all 3 processes start, they will just sit there waiting for some data. Eventually, some external process connects to port 1234 and sends some data into nc
, which writes into /tmp/f
. cat
(eventually) reads that data and sends it downstream to bash
, which processes the input and (probably) writes some data into nc
, which sends it back across the socket connection.
If you have a test case in which cat /tmp/f
only writes one line of data, that is simply because whatever process you used to write into /tmp/f
only wrote a single line. Try: printf 'foo\nbar\nbaz\n' > /tmp/f & cat /tmp/f
or while sleep 1; do date; done > /tmp/f & cat /tmp/f
CodePudding user response:
.1 You misunderstand what happen when you echo "string" >/path/fifo
.a) When you just echo something >/path/to/somewhere
, you
- (test accessibility, then) open target somewhere for writting
- write someting in openned file descriptor (
fd
) - close (relax) accessed file.
.b) A fifo (The First In is the First Out.) is not a file.
Try this:
# Window 1:
mkfifo /tmp/fifotest cat /tmp/fifotest
# Window 2:
exec {fd2fifo}>/tmp/fifotest echo >&$fd2fifo Foo bar
You will see cat
not terminating.
echo >&$fd2fifo Baz exec {fd2fifo}>&-
Now, cat will close
So there is no need of any loop!
.2 command cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f
could be written (avoid useless use of cat
):
bash -i 2>&1 </tmp/f | nc -l -p 1234 > /tmp/f
but you could do same operation but from different point of vue:
nc -l -p 1234 </tmp/f | bash -i >/tmp/f 2>&1
The goal is
- to drive bash's STDIN from
nc
's STDOUT and - connect back bash's STDOUT and STDERR to
nc
's STDIN.
.3 The more: bashism
Under bash, you could avoid creating fifo by using unnamed fifo:
coproc nc -l -p 1234; bash -i >&${COPROC[1]} 2>&1 <&${COPROC[0]}
or
exec {ncin}<> <(:); nc -l -p 1234 <&$ncin | bash -i >&$ncin 2>&1