On Tue, Feb 12, 2013 at 1:54 AM, <matei.da...@gmail.com> wrote: > With the script below, I'd expect any fd pointing to /dev/null to be > closed when the second llfd() is executed. Surprisingly, fd 3 is closed, > but fd 10 is now open, pointing to /dev/null, as if eval copied it instead > of closing it. Is this a bug? > > Thanks, > M > > > $ bash -c 'llfd () { ls -l /proc/$BASHPID/fd/; }; x=3; eval "exec > $x>/dev/null"; llfd; eval "llfd $x>&-"' > total 0 > lrwx------ 1 matei matei 64 Feb 11 18:36 0 -> /dev/pts/2 > lrwx------ 1 matei matei 64 Feb 11 18:36 1 -> /dev/pts/2 > lrwx------ 1 matei matei 64 Feb 11 18:36 2 -> /dev/pts/2 > l-wx------ 1 matei matei 64 Feb 11 18:36 3 -> /dev/null > lr-x------ 1 matei matei 64 Feb 11 18:36 8 -> /proc/4520/auxv > total 0 > lrwx------ 1 matei matei 64 Feb 11 18:36 0 -> /dev/pts/2 > lrwx------ 1 matei matei 64 Feb 11 18:36 1 -> /dev/pts/2 > l-wx------ 1 matei matei 64 Feb 11 18:36 10 -> /dev/null > lrwx------ 1 matei matei 64 Feb 11 18:36 2 -> /dev/pts/2 > lr-x------ 1 matei matei 64 Feb 11 18:36 8 -> /proc/4520/auxv > $ bash --version > GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu) > Copyright (C) 2011 Free Software Foundation, Inc. > License GPLv3+: GNU GPL version 3 or later < > http://gnu.org/licenses/gpl.html> > > This is free software; you are free to change and redistribute it. > There is NO WARRANTY, to the extent permitted by law. > $ >
Note that the same happens without using eval: $ llfd 3>&- total 0 lrwx------ 1 pgas pgas 64 Feb 12 08:00 0 -> /dev/pts/0 lrwx------ 1 pgas pgas 64 Feb 12 08:00 1 -> /dev/pts/0 l-wx------ 1 pgas pgas 64 Feb 12 08:00 10 -> /dev/null lrwx------ 1 pgas pgas 64 Feb 12 08:00 2 -> /dev/pts/0 lrwx------ 1 pgas pgas 64 Feb 12 08:00 255 -> /dev/pts/0 But you need to consider what process you are examining, you use a function and you examine the file descriptors of the process where this function runs. A function runs in the same process as the parent shell, if it simply closes 3 then there will be no more fd opened on >/dev/null in the parent shell when the function returns So what bash does is a little juggling with the file descriptors, moving 3 temporarily to be able to restore it.