I am a Bash beginner but I am trying to learn this tool to have a job in computers one of these days.
I am trying to teach myself about file descriptors now. Let me share some of my experiments:
#!/bin/bash
# Some dummy multi-line content
read -d '' colours <<- 'EOF'
red
green
blue
EOF
# File descriptor 3 produces colours
exec 3< <(echo "$colours")
# File descriptor 4 filters colours
exec 4> >(grep --color=never green)
# File descriptor 5 is an unlimited supply of violet
exec 5< <(yes violet)
echo Reading colours from file descriptor 3...
cat <&3
echo ... done.
echo Reading colours from file descriptor 3 again...
cat <&3
echo ... done.
echo Filtering colours through file descriptor 4...
echo "$colours" >&4
echo ... done. # Race condition?
echo Dipping into some violet...
head <&5
echo ... done.
echo Dipping into some more violet...
head <&5
echo ... done.
Some questions spring to mind as I see the output coming from the above:
yes
start executing? upon fd declaration? later?yes
stop (CTRL-Z
or other) and restart when more violet is needed?yes
?yes
only stop when I exec 5>&-
?>&-
or <&-
?I'll stop here, for now.
Thanks!
PS: partial (numbered) answers are fine.. I'll put together the different bits and pieces myself.. (although a comprehensive answer from a single person would be impressive!)
Use the ulimit -n command to view the number of file descriptors configured for your Linux system.
Stdin, stdout, and stderr On a Unix-like operating system, the first three file descriptors, by default, are STDIN (standard input), STDOUT (standard output), and STDERR (standard error). The default data stream for input, for example in a command pipeline.
On Linux, the set of file descriptors open in a process can be accessed under the path /proc/PID/fd/ , where PID is the process identifier. File descriptor /proc/PID/fd/0 is stdin , /proc/PID/fd/1 is stdout , and /proc/PID/fd/2 is stderr .
For utilizing the redirection of bash, execute any script, then define the > or >> operator followed by the file path to which the output should be redirected. “>>” operator is used for utilizing the command's output to a file, including the output to the file's current contents.
fd3 seems to get "depleted" after "consumption", is it also automatically closed after first use?
No, it is not closed. This is due to the way exec
works. In the mode in which you have used exec
(without arguments), its function is to arrange the shell's own file descriptors as requested by the I/O redirections specified to itself, and then leave them that way until the script terminated or they are changed again later.
Later, cat
receives a copy of this file descriptor 3 on its standard input (file descriptor 0). cat
's standard input is implicitly closed when cat
exits (or perhaps, though unlikely, cat
closes it before it exists, but that doesn't matter). The original copy of this file, which is the shell's file descriptor 3, remains. Although the actual file has reached EOF and nothing further will be read from it.
how is fd3 different from a named pipe? (something I have looked at already)
The shell's <(some command)
syntax (which is not standard bourne shell syntax and I believe is only available in zsh
and bash
, by the way) might actually be implemented using named pipes. It probably isn't under Linux because there's a better way (using /dev/fd
), but it probably is on other operating systems.
So in that sense, this syntax may or may not be a helper for setting up named pipes.
when exactly does the command yes start executing? upon fd declaration? later?
As soon as the <(yes violet)
construct is evaluated (which happens when the exec 5< <(yes violet)
is evaluated).
does yes stop (CTRL-Z or other) and restart when more violet is needed?
No, it does not stop. However, it will block soon enough when it starts producing more output than anything reading the other end of the pipe is consuming. In other words, the pipe buffer will become full.
how can I get the PID of yes?
Good question! $!
appears to contain it immediately after yes
is executed. However there seems to be an intermediate subshell and you actually get the pid of that subshell. Try <(exec yes violet)
to avoid the intermediate process.
can I get a list of "active" fds?
Not from the shell. But if you're using an operating system like Linux that has /proc
, you can just consult /proc/self/fd
.
very interesting race condition on filtering through fd4, can it be avoided?
To avoid it, you presumably want to wait for the grep
process to complete before proceeding through the script. If you obtain the process ID of that process (as above), I think you should be able to wait
for it.
will yes only stop when I exec 5>&-?
Yes. What will happen then is that yes
will continue to try to produce output forever but when the other end of the file descriptor is closed it will either get a write error (EPIPE
), or a signal (SIGPIPE
) which is fatal by default.
does it matter whether I close with >&- or <&-?
No. Both syntaxes are available for consistency's sake.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With