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 91266
, connect
with 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 Escape
, press 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
to a (gdb)
prompt. Exit gdb
.
$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
/tmp/vi_recover.txt
.
Expose Process STDIO on TCP Port
This note explains how to launch a process and connect its
stdin
/stdout
/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
tell socat
to build a PTY at /tmp/pty_test
and connect it to TCP port
4242
.
socat PTY,link=/tmp/pty_test,raw TCP-LISTEN:4242,reuseaddr,fork
Note that the PTY
argument to socat
must precede the TCP-LISTEN
argument.
Despite the bidirectional nature, the endpoint definition order is not
interchangeable.
Now we use setsid
to start a new bash
process and attach it to the PTY at
/tmp/pty_test
. Note that we collapse stdout
and stderr
into a single
combined stream.
setsid sh -c 'exec bash --login <> /tmp/pty_test >&0 2>&1'
Replace bash --login
with whatever other command you desire to execute.
Now, from the FreeBSD machine, connect the remote TCP port to your local STDIO
with socat
. Assuming the Debian machine running bash
is at 192.168.1.107
,
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.
Determine PID of X11 Window
This note explains how to determine the Process ID (PID) corresponding to a program running in an X11 window, even if the program has locked up.
I occasionally find myself needing to kill an X11 program like my terminal
emulator (st
) after it locks up, only to be greeted by a list of almost
indistinguishable processes.
% ps aux | grep st
ataylor 6358 0.0 0.0 19292 6848 - Is 18Jan21 0:00.22 st
ataylor 13449 0.0 0.0 18824 6752 - Is 11Nov20 0:12.00 st
ataylor 15194 0.0 0.0 19208 7416 - Is 4Aug20 6:22.17 st
ataylor 17303 0.0 0.0 19380 7492 - Is 16Feb21 0:08.18 st
ataylor 24875 0.0 0.0 18812 8212 - Is 24Feb21 0:05.34 st
ataylor 25313 0.0 0.0 19388 6928 - Is 21Sep20 0:04.07 st
ataylor 26013 0.0 0.0 18348 6364 - Is 29Jun20 0:27.78 st
ataylor 26677 0.0 0.0 20756 9152 - Is 20Dec20 0:00.86 st
ataylor 27383 0.0 0.0 19152 8552 - Is Fri17 0:00.96 st
ataylor 28440 0.0 0.0 18916 5100 - Is 14Mar20 0:24.59 st
ataylor 28491 0.0 0.0 18320 8528 - Is 18:22 0:03.22 st
ataylor 31469 0.0 0.0 19280 7000 - Is 13Feb21 0:10.73 st
ataylor 35707 0.0 0.0 19152 9100 - Ss 23:45 0:00.08 st
ataylor 39426 0.0 0.0 20980 7900 - Is 14Mar20 3:11.24 st
ataylor 42211 0.0 0.0 18980 9080 - Is 17:33 0:02.43 st
ataylor 50065 0.0 0.0 19000 6800 - Is 3Jan21 0:00.80 st
ataylor 50765 0.0 0.0 18764 6364 - Is 9Jan21 0:05.97 st
ataylor 50780 0.0 0.0 18896 6656 - Is 28Oct20 0:01.38 st
ataylor 53637 0.0 0.0 20568 8636 - Is 26Dec20 0:16.79 st
ataylor 68757 0.0 0.0 19836 8912 - Is 24Jan21 0:00.56 st
ataylor 69466 0.0 0.0 18980 9012 - Is Sun04 0:01.42 st
ataylor 72775 0.0 0.0 19260 7236 - Is 7Jan21 0:01.10 st
ataylor 73530 0.0 0.0 18764 6912 - Is 4Nov20 0:17.34 st
ataylor 73701 0.0 0.0 21040 9120 - Is 20Nov20 0:18.44 st
ataylor 75901 0.0 0.0 18456 7640 - Is 8Feb21 0:28.57 st
ataylor 80220 0.0 0.0 18884 6756 - Is 25Dec20 0:04.87 st
ataylor 81521 0.0 0.0 18496 8652 - Is 01:04 0:12.21 st
ataylor 83818 0.0 0.0 18956 5072 - Is 10Apr20 0:09.37 st
ataylor 89395 0.0 0.0 18920 4984 - Is 15Apr20 0:11.99 st
Use xprop
to obtain the PID from the window’s various X11-related properties.
First, run the command xprop _NET_WM_PID
. It will appear to hang, but your
mouse cursor will change to crosshairs. Place the crosshairs over the X11
window in question and click. This tells xprop
which window you are
interested in and xprop
then tells you the PID. For example, if I click on
one of the st
windows from the previous example, we see that it is PID 75901.
% xprop _NET_WM_PID
_NET_WM_PID(CARDINAL) = 75901