While writing a post on
file descriptors, I ended up on a tangent trying to answer a question that seemed like it should be simple and obvious. How do you close arbitrary file descriptors in a bash shell script? The chapter on
I/O Redirection in the
Advanced Bash-Scripting Guide shows the typical examples that you see everywhere. All of these examples use a hardcoded number to identify the descriptor, not a variable. Try to use a variable and bash gets confused thinking the value is the name of a command you wish to execute. For example:
#!/bin/bash
num=5
exec $num>&-
When you run it yields:
$ ./test.sh
./test.sh: line 3: exec: 5: not found
I eventually found the answer on another blog that had a post about
daemonizing bash. The technique is to use the built-in
eval command. The variable will be substituted in a string and the string will get executed by eval. It is kind of obvious once I saw how someone else had done it, but for whatever reason it did not occur to me. Since I like examples, here is a script with a closefd function for closing file descriptors:
#!/bin/bash
function closefd {
local fd=$1
echo "closing $fd"
eval "
exec $fd>&-
exec $fd<&-
"
}
function listfds {
local pid=$1
local label=$2
ls /proc/$pid/fd | sort -n | awk '{printf("%s ", $1)}' | sed "s/^/$label: /"
echo ""
}
# Record the PID of this shell, need to make sure we are tracking fds of this
# shell and not some forked child
pid=$$
# Run commands
listfds $pid "before"
closefd 5
listfds $pid "middle"
closefd 13
listfds $pid "after"
You can run this script with a simple wrapper that opens up a bunch of files that will be inherited when a new process is forked. In my case I used the testclose C program from the
forking file descriptors post after removing the call to closefrom. Running the script shows output like:
$ ./testclose closefd.sh
opened 20 files
before: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 255
closing 5
middle: 0 1 2 3 4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 255
closing 13
after: 0 1 2 3 4 6 7 8 9 10 11 12 14 15 16 17 18 19 20 21 22 255
child 20710 exited with status 0
No comments:
Post a Comment