Redirect File Descriptor of Running Process
This note explains how to redirect
stdin (or any other file descriptor) of a
pre-existing process using the GNU debugger (
gdb) and a FIFO. It was tested
on FreeBSD 11.
An example of use would be saving the contents of remote
vi sessions after
they are detached due to a dropped connection.
First, make a FIFO:
$ mkfifo /tmp/vififo
Assuming there is a pre-existing
vi session with PID
gdb, close file descriptor
0 and reopen it as a connection to the
FIFO with the
call close and
call open commands.
$ gdb -p 91266 <snip> Attaching to process 91266 <snip> (gdb) call close (0) $1 = 0 (gdb) call open ("/tmp/vififo", 0600)
At this point
gdb will appear to hang. Leave it and open a new terminal. Use
echo to send characters to the process through the FIFO.
Special characters may be escaped by pressing
Ctrl-V followed by the
character. For example, to send an
Ctrl-V followed by
Escape which results in an
Escape code, or
Continuing the example, tell
vi to save the current buffer to a file.
$ echo "^[:w /tmp/vi_recover.txt" > /tmp/vififo
After this command the
gdb session should start responding again, returning
(gdb) prompt. Exit
$2 = 0 (gdb) quit A debugging session is active. Inferior 1 [process 91266] will be detached. Quit anyway? (y or n) Y Detaching from program: /hh/bin/vi, process 91266 [Inferior 1 (process 91266) detached]
The characters have now been received by
vi and a file should be waiting at
Expose Process STDIO on TCP Port
This note explains how to launch a process and connect its
stderr directly to a TCP port. It was tested on FreeBSD 12.
As an example, we will launch a
bash process running on a Debian 10 machine
and connect it to TCP port
4242. Then, from a FreeBSD machine we will connect
and utilize the
bash session remotely.
First, on the Debian machine, we use
socat, a program which establishes two
bidirectional byte streams and transfers data between them. In our case, we
socat to build a PTY at
/tmp/pty_test and connect it to TCP port
socat PTY,link=/tmp/pty_test,raw TCP-LISTEN:4242,reuseaddr,fork
Note that the
PTY argument to
socat must precede the
Despite the bidirectional nature, the endpoint definition order is not
Now we use
setsid to start a new
bash process and attach it to the PTY at
/tmp/pty_test. Note that we collapse
stderr into a single
setsid sh -c 'exec bash --login <> /tmp/pty_test >&0 2>&1'
bash --login with whatever other command you desire to execute.
Now, from the FreeBSD machine, connect the remote TCP port to your local STDIO
socat. Assuming the Debian machine running
bash is at
execute the following command.
socat STDIO,raw TCP:192.168.1.107:4242
At this point you have a fully interative
bash session running on the Debian
machine, controlled from the FreeBSD machine.