Search code examples
linuxbashfile-descriptor

Linux: check if file descriptor is available for reading


Considering the following example, emulating a command which gives output after 10 seconds: exec 5< <(sleep 10; pwd)

In Solaris, if I check the file descriptor earlier than 10 seconds, I can see that it has a size of 0 and this tells me that it hasn't been populated with data yet. I can simply check every second until the file test condition is met (different from 0) and then pull the data:

while true; do
    if [[ -s /proc/$$/fd/5 ]]; then
        variable=$(cat <&5)
        break
    fi
    sleep 1
done

But in Linux I can't do this (RedHat, Debian etc). All file descriptors appear with a size of 64 bytes no matter if they hold data or not. For various commands that will take a variable amount of time to dump their output, I will not know when I should read the file descriptor. No, I don't want to just wait for cat <&5 to finish, I need to know when I should perform the cat in the first place. Because I am using this mechanism to issue simultaneous commands and assign their output to corresponding file descriptors. As mentioned already, this works great in Solaris.


Solution

  • Here is the skeleton of an idea :

    #!/bin/bash
    exec 5< <(sleep 4; pwd)
    while true
    do
      if
        read -t 0 -u 5 dummy
      then
        echo Data available
        cat <&5
        break
      else
        echo No data
      fi
      sleep 1
    done
    

    From the Bash reference manual :

    If timeout is 0, read returns immediately, without trying to read and data. The exit status is 0 if input is available on the specified file descriptor, non-zero otherwise.

    The idea is to use read with -t 0 (to have zero timeout) and -u 5 (read from file descriptor 5) to instantly check for data availability.

    Of course this is just a toy loop to demonstrate the concept.