| 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`. |
| 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. |
| 91 | |
| 92 | |
| 93 | # Determine PID of X11 Window # |
| 94 | |
| 95 | This note explains how to determine the Process ID (PID) corresponding to a |
| 96 | program running in an X11 window, even if the program has locked up. |
| 97 | |
| 98 | I occasionally find myself needing to kill an X11 program like my terminal |
| 99 | emulator (`st`) after it locks up, only to be greeted by list of almost |
| 100 | indistinguishable processes. |
| 101 | |
| 102 | % ps aux | grep st |
| 103 | ataylor 6358 0.0 0.0 19292 6848 - Is 18Jan21 0:00.22 st |
| 104 | ataylor 13449 0.0 0.0 18824 6752 - Is 11Nov20 0:12.00 st |
| 105 | ataylor 15194 0.0 0.0 19208 7416 - Is 4Aug20 6:22.17 st |
| 106 | ataylor 17303 0.0 0.0 19380 7492 - Is 16Feb21 0:08.18 st |
| 107 | ataylor 24875 0.0 0.0 18812 8212 - Is 24Feb21 0:05.34 st |
| 108 | ataylor 25313 0.0 0.0 19388 6928 - Is 21Sep20 0:04.07 st |
| 109 | ataylor 26013 0.0 0.0 18348 6364 - Is 29Jun20 0:27.78 st |
| 110 | ataylor 26677 0.0 0.0 20756 9152 - Is 20Dec20 0:00.86 st |
| 111 | ataylor 27383 0.0 0.0 19152 8552 - Is Fri17 0:00.96 st |
| 112 | ataylor 28440 0.0 0.0 18916 5100 - Is 14Mar20 0:24.59 st |
| 113 | ataylor 28491 0.0 0.0 18320 8528 - Is 18:22 0:03.22 st |
| 114 | ataylor 31469 0.0 0.0 19280 7000 - Is 13Feb21 0:10.73 st |
| 115 | ataylor 35707 0.0 0.0 19152 9100 - Ss 23:45 0:00.08 st |
| 116 | ataylor 39426 0.0 0.0 20980 7900 - Is 14Mar20 3:11.24 st |
| 117 | ataylor 42211 0.0 0.0 18980 9080 - Is 17:33 0:02.43 st |
| 118 | ataylor 50065 0.0 0.0 19000 6800 - Is 3Jan21 0:00.80 st |
| 119 | ataylor 50765 0.0 0.0 18764 6364 - Is 9Jan21 0:05.97 st |
| 120 | ataylor 50780 0.0 0.0 18896 6656 - Is 28Oct20 0:01.38 st |
| 121 | ataylor 53637 0.0 0.0 20568 8636 - Is 26Dec20 0:16.79 st |
| 122 | ataylor 68757 0.0 0.0 19836 8912 - Is 24Jan21 0:00.56 st |
| 123 | ataylor 69466 0.0 0.0 18980 9012 - Is Sun04 0:01.42 st |
| 124 | ataylor 72775 0.0 0.0 19260 7236 - Is 7Jan21 0:01.10 st |
| 125 | ataylor 73530 0.0 0.0 18764 6912 - Is 4Nov20 0:17.34 st |
| 126 | ataylor 73701 0.0 0.0 21040 9120 - Is 20Nov20 0:18.44 st |
| 127 | ataylor 75901 0.0 0.0 18456 7640 - Is 8Feb21 0:28.57 st |
| 128 | ataylor 80220 0.0 0.0 18884 6756 - Is 25Dec20 0:04.87 st |
| 129 | ataylor 81521 0.0 0.0 18496 8652 - Is 01:04 0:12.21 st |
| 130 | ataylor 83818 0.0 0.0 18956 5072 - Is 10Apr20 0:09.37 st |
| 131 | ataylor 89395 0.0 0.0 18920 4984 - Is 15Apr20 0:11.99 st |
| 132 | |
| 133 | Use `xprop` to obtain the PID from the window's various X11-related properties. |
| 134 | First, run the command `xprop _NET_WM_PID`. It will appear to hang, but your |
| 135 | mouse cursor will change to crosshairs. Place the crosshairs over the X11 |
| 136 | window in question and click. This tells `xprop` which window you are |
| 137 | interested in and `xprop` then tells you the PID. For example, if I click on |
| 138 | one of the `st` windows from the previous example, we see that it is PID 75901. |
| 139 | |
| 140 | % xprop _NET_WM_PID |
| 141 | _NET_WM_PID(CARDINAL) = 75901 |
| 142 | |