Why can't I `tail -f /proc/$pid/fd/1`?
Solution 1
Make a strace
of tail -f
, it explains everything. The interesting part:
13791 fstat(3, {st_mode=S_IFREG|0644, st_size=139, ...}) = 0
13791 fstatfs(3, {...}) = 0
13791 inotify_init() = 4
13791 inotify_add_watch(4, "/path/to/file", IN_MODIFY|IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF) = 1
13791 fstat(3, {st_mode=S_IFREG|0644, st_size=139, ...}) = 0
13791 read(4, 0xd981c0, 26) = -1 EINTR (Interrupted system call)
What it does? It sets up an inotify
handler to the file, and then waits until something happens with this file. If the kernel says tail
through this inotify handler, that the file changed (normally, was appended), then tail
1) seeks 2) reads the changes 3) writes them out to the screen.
/proc/3844/fd/1
on your system is a symbolic link to /dev/pts/14
, which is a character device. There is no such thing as some like a "memory map", which could be accessed by that. Thus, there is nothing whose changes could be signed to the inotify, because there is no disk or memory area which could be accessed by that.
This character device is a virtual terminal, which practically works as as if it were a network socket. Programs running on this virtual terminal are connecting to this device (just as if you telnet-ted into a tcp port), and writing what they want to write into. There are complexer things as well, for example locking the screen, terminal control sequences and such, these are normally handled by ioctl()
calls.
I think, you want to somehow watch a virtual terminal. It can be done on linux, but it is not so simple, it needs some network proxy-like functionality, and a little bit of tricky usage of these ioctl()
calls. But there are tools which can do that.
Currently I can't remember, which debian package has the tool for this goal, but with a little googling you could find that probably easily.
Extension: as @Jajesh mentioned here (give him a +1 if you gave me), the tool is named watch
.
Extension #2: @kelnos mentioned, a simple cat /dev/pts/14
were also enough. I tried that, and yes, it worked, but not correctly. I didn't experimented a lot with that, but it seems to me as if an output going into that virtual terminal gone either to the cat
command, or to its original location, and never to both. But it is not sure.
Solution 2
Files in /dev/pts
are not regular files, they are handles for virtual terminals.
A pts
behavior for reading and writing is not symmetrical (that is, what's written in there can later be read from it, like a regular file or a fifo/pipe), but mediated by the process which created the virtual terminal: some common ones are xterm or ssh or agetty or screen. The controlling process will usually dispatch key presses to processes which read the pts
file, and render on screen what they write on the pts
.
Thus, tail -f /dev/pts/14
will print the keys you tap on the terminal from which you started your script, and if you do echo meh > /dev/pts/14
the meh
message will appear in the terminal.
Juan Carlos Kuri Pinto
Updated on September 18, 2022Comments
-
Juan Carlos Kuri Pinto over 1 year
How can I obtain a list of combinations from a list of lists?
For example:
ghci> getCombinations [[1,2,3],[10,20,30],[100,200,300]] [[1,10,100],[1,10,200],[1,10,300],[1,20,100],[1,20,200],[1,20,300],[1,30,100], [1,30,200],[1,30,300],[2,10,100],[2,10,200],[2,10,300],[2,20,100],[2,20,200], [2,20,300],[2,30,100],[2,30,200],[2,30,300],[3,10,100],[3,10,200],[3,10,300], [3,20,100],[3,20,200],[3,20,300],[3,30,100],[3,30,200],[3,30,300]]
-
Matt Fenwick about 11 yearspossible duplicate of Calculate n-ary Cartesian Product
-
Admin over 9 years
-
-
Daniel Fischer about 11 yearsThe simpler version, without the need for an
import
, issequence
. -
Juan Carlos Kuri Pinto about 11 yearsLOL! You are right: sequence [[1,2,3],[10,20,30],[100,200,300]]
-
kelnos over 9 yearspeterh's answer about
tail
is correct (the inotify watch bit), but he's incorrect in that it's actually very simple to do what you want: simply usecat
instead oftail
. -
peterh over 9 years@kelnos Thanks, I will try that and extend my answer with the results.
-
Ángel over 9 yearsThis command will show the list of open fds every 2 seconds, not the content output on stdout.
-
Jayesh over 9 yearsÁngel, true. He could use the watch with a cat to see the result on which descriptor he wants to monitor. I guess @peter-horvath, gave the perfect explanation for the question.
-
cprn over 9 yearsI know
watch
. What I'm trying to do is to peek the output of the already running process, sowatch
doesn't help. -
cprn over 9 years@kelnos
cat
doesn't work for me either, it hangs the same way tail does and all I can do is toctrl+c
. -
cprn over 9 yearsI still don't get it. I changed
echo $$
toecho $$ >> foo
so now there's a file and process opens it and appends to it every 0.5 seconds. I still can't access it via file descriptor and all file descriptors in/proc/$pid/fd/
(but 254 which links totest.sh
script itself) link to/dev/pts/14
. How does bash accessfoo
it writes to? -
peterh over 9 yearsFirst, you didn't read this: Currently I can't remember, which debian package has the tool for this goal, but with a little googling you could find that probably easily. Second: screen -r -x can do what you want, but it works only for screen sessions.
-
kelnos over 9 yearsodd, it appears to only work in some situations. using the script in the question, it doesn't work. but if i do "echo $$" in a shell, and then cat FD 1 on that pid in another shell, everything i type in the first shell is echoed in the second.