Basics
A Linux file descriptor is an integer for accessing a file like object(file, socket, FIFO, ... ). File descriptors is a per process concept, we may get a list of file descriptor of a process at
/proc/PID/fd/
or use command lsof:
lsof -p pid
Standard input, output and error
Every process have 3 file descriptors in default: that is 0 for stdin, 1 for stdout, and 2 for stderr. For example, a shell command "cmd > log.txt" only pipe the stdout of cmd to log.txt in default. Use "cmd > log.txt 2>&1" will pipe both the stdout and the stderr to the log.txt file. "2>&1" means redirecting stderr to stdout.
For example:
python -c "import sys;sys.stdout.write('abc')" > abc.txt
python -c "import sys;sys.stdout.write('abc')" > abc.txt
abc.txt will be 'abc'.
python -c "import sys;sys.stderr.write('abc\n')" > abc.txt 2>&1
abc.txt will be a blank file.
python -c "import sys;sys.stderr.write('abc\n')" > abc.txt 2>&1
abc.txt will be 'abc'.
Duplicate File Descriptor
We may duplicate file descriptor in a process. For example, in process(PID=28833), if we have
f = open('test')
We may get the following from the lsof -p 28833:
python 28833 ubuntu 3r REG 252,0 581 134489 /home/ubuntu/test
And we can use os.dup to duplicate the file descriptor of f by
fd2 = os.dup(f.fileno())
See what we may get the from lsof:
python 28833 ubuntu 3r REG 252,0 581 134489 /home/ubuntu/test
python 28833 ubuntu 4r REG 252,0 581 134489 /home/ubuntu/test
And we can use f2 = os.fdopen(f2), and operate f2 as f.
Now let's create f3=open('/dev/null'), so we have the following in lsof:
python 28833 ubuntu 5r CHR 1,3 0t0 1331 /dev/null
If we use os.dup2 as below:
os.dup2(f.fileno(), f3.fileno())
os.dup2(f.fileno(), f3.fileno())
We may get:
python 28833 ubuntu 3r REG 252,0 581 134489 /home/ubuntu/test
python 28833 ubuntu 4r REG 252,0 581 134489 /home/ubuntu/test
python 28833 ubuntu 5r REG 252,0 581 134489 /home/ubuntu/test
Comments