Commit | Line | Data |
---|---|---|
a8f095b0 AT |
1 | # Redirect File Descriptor of Running Process # |
2 | ||
3 | This note explains how to redirect `stdin` (or any other file descriptor) of a | |
4 | pre-existing process using the GNU debugger (`gdb`) and a FIFO. It was tested | |
5 | on FreeBSD 11. | |
6 | ||
7 | An example of use would be saving the contents of remote `vi` sessions after | |
8 | they are detached due to a dropped connection. | |
9 | ||
10 | First, make a FIFO: | |
11 | ||
12 | $ mkfifo /tmp/vififo | |
13 | ||
14 | Assuming there is a pre-existing `vi` session with PID `91266`, connect | |
15 | with `gdb`, close file descriptor `0` and reopen it as a connection to the | |
16 | FIFO with the `call close` and `call open` commands. | |
17 | ||
18 | $ gdb -p 91266 | |
19 | <snip> | |
20 | Attaching to process 91266 | |
21 | <snip> | |
22 | (gdb) call close (0) | |
23 | $1 = 0 | |
24 | (gdb) call open ("/tmp/vififo", 0600) | |
25 | ||
26 | At this point `gdb` will appear to hang. Leave it and open a new terminal. Use | |
27 | `echo` to send characters to the process through the FIFO. | |
28 | ||
29 | Special characters may be escaped by pressing `Ctrl-V` followed by the | |
30 | character. For example, to send an `Escape`, press `Ctrl-V` followed by | |
31 | `Escape` which results in an `Escape` code, or `^[`. | |
32 | ||
33 | Continuing the example, tell `vi` to save the current buffer to a file. | |
34 | ||
35 | $ echo "^[:w /tmp/vi_recover.txt" > /tmp/vififo | |
36 | ||
37 | After this command the `gdb` session should start responding again, returning | |
38 | to a `(gdb)` prompt. Exit `gdb`. | |
39 | ||
40 | $2 = 0 | |
41 | (gdb) quit | |
42 | A debugging session is active. | |
43 | ||
44 | Inferior 1 [process 91266] will be detached. | |
45 | ||
46 | Quit anyway? (y or n) Y | |
47 | Detaching from program: /hh/bin/vi, process 91266 | |
48 | [Inferior 1 (process 91266) detached] | |
49 | ||
50 | The characters have now been received by `vi` and a file should be waiting at | |
51 | `/tmp/vi_recover.txt`. | |
08f3fbf9 AT |
52 | |
53 | ||
54 | # Expose Process STDIO on TCP Port # | |
55 | ||
56 | This note explains how to launch a process and connect its | |
57 | `stdin`/`stdout`/`stderr` directly to a TCP port. It was tested on FreeBSD 12. | |
58 | ||
59 | As an example, we will launch a `bash` process running on a Debian 10 machine | |
60 | and connect it to TCP port `4242`. Then, from a FreeBSD machine we will connect | |
61 | and utilize the `bash` session remotely. | |
62 | ||
63 | First, on the Debian machine, we use | |
64 | [`socat`](http://www.dest-unreach.org/socat/), a program which establishes two | |
65 | bidirectional byte streams and transfers data between them. In our case, we | |
66 | tell `socat` to build a PTY at `/tmp/pty_test` and connect it to TCP port | |
67 | `4242`. | |
68 | ||
69 | socat PTY,link=/tmp/pty_test,raw TCP-LISTEN:4242,reuseaddr,fork | |
70 | ||
71 | Note that the `PTY` argument to `socat` must precede the `TCP-LISTEN` argument. | |
72 | Despite the bidirectional nature, the endpoint definition order is not | |
73 | interchangeable. | |
74 | ||
75 | Now we use `setsid` to start a new `bash` process and attach it to the PTY at | |
76 | `/tmp/pty_test`. Note that we collapse `stdout` and `stderr` into a single | |
77 | combined stream. | |
78 | ||
79 | setsid sh -c 'exec bash --login <> /tmp/pty_test >&0 2>&1' | |
80 | ||
81 | Replace `bash --login` with whatever other command you desire to execute. | |
82 | ||
83 | Now, from the FreeBSD machine, connect the remote TCP port to your local STDIO | |
84 | with `socat`. Assuming the Debian machine running `bash` is at `192.168.1.107`, | |
85 | execute the following command. | |
86 | ||
87 | socat STDIO,raw TCP:192.168.1.107:4242 | |
88 | ||
89 | At this point you have a fully interative `bash` session running on the Debian | |
90 | machine, controlled from the FreeBSD machine. |