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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.