Find the answer to your Linux question:
Results 1 to 6 of 6
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1

    SOLVED: bash stdin problem

    Today I ran into a strange stdin problem with bash (3.1.17). I have a script that optionally allows input from stdin like:
    echo "text stream" | myscript
    or can be called like:

    Now I also need it to be able to take input from stdin inside the script like:
    read -p "Enter something: " ans
    which only works when I do not have a stream piped into the script at invocation.

    I think that I need to somehow disconnect stdin from external and reconnect it again to &0. I've tried a number of things like this but no luck yet.

    here is a test script that exhibits the issue:
    if [ "$1" == "--help" ]; then
    echo "USAGE: scriptname";
    echo "USAGE: echo "some string" | scriptname"
    exit 0
    read -t 1 incoming
    echo "incoming: $incoming"
    read -p "Enter something: " ans
    echo "You entered: $ans"

    test case 1:
    echo "some string" | myscript
    test case 2:

    Test case 2 works fine. Test case 1 fails because the second read fails to wait for input.

    So how to reset stdin so the second read will wait for input?

  2. #2
    Linux Guru Cabhan's Avatar
    Join Date
    Jan 2005
    Seattle, WA, USA
    You can't "reconnect to &0". This is because your program only knows about ONE stdin: the stdin it was given by the shell. As far as it knows, there is no other stdin. You would need to tell it what that stdin is.

    You can tell this by using the 'tty' command. This command tells you the filename of the terminal attached to stdin. However, if you run it when piping, you will see that it is "not a terminal".

    I don't know if this is even possible, unless you somehow know the filename of the terminal in advance (for instance, supplying it as a parameter). Indeed, the whole point of abstracting stdin away from the terminal is that programs don't have to be associated with the terminal.

    I'd be interested to see if you find a reliable way to do this.

  3. #3
    I can close the existing stdin with:
    exec 0<&-
    And of course this results in broken pipe errors to the shell.
    Now I would need to reopen stdin as it would be in a non-piped shell but is it possible? I would need to do something like:
    exec < ?????
    But to what device? /dev/stdin is what you would want but it is now gone.


  4. $spacer_open
  5. #4

    SOLVED: bash stdin problem

    Caveat: This solution works for Linux and other OS may have to adjust accordingly.

    The key was finding the terminal to reattach to stdin:

    term="/dev/$(ps -p$$ --no-heading | awk '{print $2}')"

    Now you can do:
    exec < $term

    And everything works.

  6. #5
    I know it's an old thread, however it was the first result from Google with the solution, however your right in saying it needs adapting for other OSs.

    The following works on OSX and Linux (well, Ubuntu at least):
    term="/dev/$(ps -p$$ -o tty="")"
    exec < $term

  7. #6
    Join Date
    May 2004
    arch linux
    Guys, this thread is nearing 5 years old so I'm going to close it, but please feel free to start fresh threads of our own if you are having any issues with Linux.

    Thank you.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts