Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sh: How do I avoid clobbering numbered file descriptors?

When I have

  exec 3>>file               # file descriptor 3 now points to file
  [ $dryrun ] && exec 3>&1   # or possibly to stdout
  echo "running">&3
  exec 3>&-                  # and is now closed

I'm worried about what file descriptor 3 may have pointed to outside of the function in question. How can I handle this?

  • Is there a builtin next_available_fd?
  • Is there a way to duplicate fd3 to a variable, then dup it back once the function is done?
    • and should I worry about threading and concurrent writes to fd3 in this case?
  • I'm in sh, but maybe bash/ksh/zsh has an answer to this?
like image 804
Ternary Avatar asked Jun 30 '11 16:06

Ternary


People also ask

Where are the file descriptors stored?

All file descriptors that a process contains are stored in the directory /proc/PID/fd/ . We had already talked a bit about the /proc file system. This directory holds information about processes. Every process has a directory in this filesystem and stores its relevant data within that directory.

What is file descriptor in shell script?

In Unix and Unix-like computer operating systems, a file descriptor (FD, less frequently fildes) is a process-unique identifier (handle) for a file or other input/output resource, such as a pipe or network socket.


2 Answers

Instead of using exec to redirect the file descriptor within the function, you can (with bash, I haven't tried with other shells) do:

foo() {
  test $dryrun && exec 3>&1
  echo running >&3
} 3>>file

foo
more_commands

In this setup, "running" will go to either the file or to the original stdout depending on $dryrun, and more_commands will have fd 3 as it was before foo was called.

like image 108
William Pursell Avatar answered Oct 16 '22 01:10

William Pursell


I don't know about anything as simple as next_available_fd, but to get the functionality that you want (temporarily redirecting a file descriptor without affecting it outside the function) can be accomplished as follows in bash (I don't know about sh):

exec 3>file3
exec 1>file1

echo "something">&3
echo "something else"

f31 () {
        echo "something">&3
}
f31 3>&1

f13 () {
        echo "something else"
}
f13 >&3

echo "something">&3
echo "something else"

The resulting file1:

something else
something
something else

And file3:

something
something else
something

Which demonstrates that the redirection is restricted to the function call in each case.

like image 1
trutheality Avatar answered Oct 16 '22 00:10

trutheality