I'm working on some script that being run by rc.local
at startup, and I noticed that output redirection works quite strange.
If I write something like echo "foo" >&1
, it ends up in syslog, and all is okay.
But when I write echo "foo" >>/dev/stdout
, or echo "foo" >>/proc/self/fd/1
, I got an error saying that there is no such device or address.
Further investigation revealed that /proc/self/fd/1
was in fact a socket.
Including ls -l /proc/self/fd
in rc.local
prints the following:
lr-x------. 1 root root 64 Jul 14 05:28 0 -> /dev/null
lrwx------. 1 root root 64 Jul 14 05:28 1 -> socket:[18485]
lrwx------. 1 root root 64 Jul 14 05:28 2 -> socket:[18485]
lr-x------. 1 root root 64 Jul 14 05:28 255 -> /etc/rc.d/rc.local
The described behaviour can be easily reproduced with nc
. First, find out which file descriptor binds to socket. You can do it by issuing nc -l -p 25566 -c "ls -l /proc/self/fd"
in first terminal and then telnet localhost 25566
in other terminal. In my case it was 5-th descriptor.
Okay. Then, to reproduce the issue, in first terminal:
nc -l -p 25566 -c "echo 'hello' >&5"
in second terminal:
telnet localhost 25566
You shall see "hello" in second terminal output between telnet messages about connection being established and closed.
Now the case with file descriptor pseudo-file from /proc
:
first terminal:
nc -l -p 25566 -c "echo 'hello' >/proc/self/fd/5"
second terminal:
telnet localhost 25566
Now second terminal just contains telnet messages about connection established and immediately closed, and first terminal shows an error: sh: /proc/self/fd/5: No such device or address
.
Edit: OS is Fedora 23 i686 server
So, the question. What's the difference between >&1
and >/proc/self/fd/1
? And is there some universal and reliable way to redirect output to some file, which corresponds exactly to current standard output?
Thank you.
Edit 2:
For clarity, exact input/output for Fedora 23 i686 for above case:
Terminal 1 | Terminal 2
$ nc -l -p 25566 -c 'ls -go /proc/self/fd' |
| $ telnet localhost 25566
| Trying ::1...
| Connected to localhost.
| Escape character is '^]'.
| total 0
| lr-x------ 1 64 Jul 14 08:56 0 -> pipe:[19687]
| l-wx------ 1 64 Jul 14 08:56 1 -> pipe:[19688]
| lrwx------ 1 64 Jul 14 08:56 2 -> /dev/tty2
| lr-x------ 1 64 Jul 14 08:56 3 -> pipe:[19687]
| lr-x------ 1 64 Jul 14 08:56 4 -> /proc/1285/fd
| lrwx------ 1 64 Jul 14 08:56 5 -> socket:[19686]
| l-wx------ 1 64 Jul 14 08:56 7 -> /pipe:[19688]
| Connection closed by foreign host.
$ nc -l -p 25566 -c "echo 'hi' >&5" |
| $ telnet localhost 25566
| Trying ::1...
| Connected to localhost.
| Escape character is '^]'.
| hi
| Connection closed by foreign host.
$ nc -l -p 25566 -c "echo 'hi' >/proc/self/fd/5" |
| $ telnet localhost 25566
| Trying ::1...
| Connected to localhost.
sh: /proc/self/fd/5: No such device or address | Escape character is '^]'.
| Connection closed by foreign host.
$ | $
nc -l -p 25566 -c "ls -l /proc/self/fd"
I get the socket attached tofd/0
andfd/1
this is what I expected. – ctrl-alt-delor Jul 14 '16 at 14:49echo >&1
line, it's just I pinpointed the problem and thought that for clarity it would be nice to go academic. – alexey.e.egorov Jul 14 '16 at 15:51fd
s open, I just have 4 and they are what I would expect.0
and1
are connected to a socket, that is whatnc
does (connect stdin and stdout to a network socket). Yours seem to be connected to a pipe (that makes no sence).2
is connected to a/dev/pts
(terminal), well I did not redirect. Yours to/dev/tty
(just a different spelling),3
to/proc/xxxx/fd
(the directory where this info is), for you this is on4
, but then you have a load of other stuff, pipes on stdin/stdout, and 2 more pipes, – ctrl-alt-delor Jul 14 '16 at 21:58nc -l -p 25566 -c "echo 'hi' >/proc/self/fd/1"
, this is how mine is wired, and hownc
should wire it, and how yours seems to be wired if you do not look to close (see your first command:nc -l -p 25566 -c 'ls -go /proc/self/fd'
it is not redirected so it goes to fd1, but we see that it goes through the socket, as telnet prints the result. As expected), I am wondering if those two pipes looping back on them selfs and the socket in a strange location, is just readhats way to get it to work, and you are not supposed to look inside, just use it. – ctrl-alt-delor Jul 14 '16 at 22:05