2

I wish to write a script that will use up all of the available file descriptors on my Linux machine. I am unsure how exactly to do this, or if it is even possible? But I wish to use this script for a 'chaos monkey' type experiment on my Linux VM.

I'd prefer for the script to be in bash, but I am not too fussy regarding this.

2 Answers 2

2

This will do it (in about 40 seconds on my system):

#!/bin/bash
[ "$BASHPID" = "$$" ] || { echo "Must run in a new process group"; exit 1; }>&2
cnt0() { cnt0=$#; }
cnt1() { cnt1=$#; }

tmpd=
trap 'rm -rf "$tmpd"; exit 1' INT HUP QUIT EXIT
tmpd=$(mktemp -d)
mkfifo "$tmpd/fifo"
exec 4<>"$tmpd/fifo"
rm -rf "$tmpd"
trap - INT HUP QUIT EXIT


open_all()
{ 
    cnt0 /proc/self/fd/*; 
    while exec {fd}</dev/null; do :; done; 
    cnt1 /proc/self/fd/*;
    nopened=$((cnt1-cnt0));
    echo $nopened >&4;
    cat /proc/sys/fs/file-nr
    if ((nopened)); then
        sleep 10000000
    fi
}

( open_all )&
while :; do
    if read nopened <&4 && ((nopened)); then
        ( open_all )&
        continue
    fi
    break
done
kill -TERM -$$

It works by opening /dev/null in a subshell as many times as possible (it should work about 1000-4000 times depending on your ulimit -n). If at least one filedescriptor was opened, the parent is notified via a pipe and the subshell is suspended with sleep. The parent process responds to a sucessful fd-allocation in the child by continuing the process in another subshell until one subshell fails.

/proc/sys/fs/file-nr is catted on each iteration to let you know how the process continues.

At the end of the process, you should get something like:

...
778192  0       786806
779248  0       786806
780272  0       786806
781264  0       786806
782256  0       786806
783280  0       786806
784304  0       786806
785328  0       786806
786352  0       786806
./open_all: line 35: cannot redirect standard input from /dev/null: Too many open files in system
./open_all: line 18: fd: Too many open files in system
Terminated

One interesting thing I learned from this is that duplicated filedescriptors (from dup or fork) don't count towards the limit (spawning a process from a parent process with many filedescriptors doesn't increase the count).

1

Shell

while true ; do cat > $(( $RANDOM * $RANDOM )).file & done; You probably will hit maxprocess limit if not root. If so, use one perl process to open files. You can lower maxfiles with sysctl, though I don't know the variable off-hand.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .