Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Is there a way to determine if a script is waiting on stdin and cause the command to exit if detected?

Here's an example, the command I'm executing takes a long time to run, but it will also prompt for input before starting w/o a prompt. I want to know the command is actually doing something and not just waiting.

Provided the following script called ./demo

#!/bin/bash

read

Is there a way to detect that read is waiting on stdin? Something like

failifwaitingonstdin | ./demo

Which would immediately return as soon as the read command was detected.

Updated:

Folks have suggested programs like expect and yes. After digging through yes, I see how they're able to support this style of interaction. They're constantly using fputs to write 'y' to stdout. Instead of doing this infinitely, I can simply return an error as soon as fputs returns on a write to stdout.

share|improve this question
add comment

4 Answers 4

up vote 7 down vote accepted

It would really help if you were a lot more specific about your script and/or command. But in case what you want to do is test where stdin is coming from you, this example script will demonstrate that for you:

#!/bin/bash
if [[ -p /dev/stdin ]]
then
    echo "stdin is coming from a pipe"
fi
if [[ -t 0 ]]
then
    echo "stdin is coming from the terminal"
fi
if [[ ! -t 0 && ! -p /dev/stdin ]]
then
    echo "stdin is redirected"
fi
read
echo $REPLY

Example runs:

$ echo "hi" | ./demo
stdin is coming from a pipe
$ ./demo
[press ctrl-d]
stdin is coming from the terminal
$ ./demo < inputfile
stdin is redirected
$ ./demo <<< hello
stdin is redirected
$ ./demo <<EOF
goodbye
EOF
stdin is redirected
share|improve this answer
    
On your second command: $ ./demo...you say you need to press Ctrl-d. I was not able to reproduce (i.e. I think you need a read somewhere in your script. To my question, how can I detect when read is waiting for input? I updated my question with more detail. –  Noah Campbell Jul 1 '10 at 3:58
    
If your program doesn't need any real input from stdin, then Gerald's suggestion of piping yes into it will make it continue since it will have that for input. Do you have the ability to modify the script? Can't you just add the test from my demo before the read in your script?: if [[ -t 0 ]]; then exit 1; done You can instead put a timeout on the read command: read -t 5 will wait for input for 5 seconds then fail if there's none. –  Dennis Williamson Jul 1 '10 at 7:11
    
The demo script is not mine, so it's unmodifiable. –  Noah Campbell Jul 2 '10 at 17:03
add comment

If you're on Linux you could use strace to see if the process is trying to read from stdin. Other platforms have similar programs (e.g. dtrace, ktrace, or truss).

You might be able to avoid the issue altogether by feeding the output of yes to the command in question.

share|improve this answer
add comment

If you are writing the scripts: bash's read builtin takes a timeout option:

read -p prompt -t 5 var # 5s timeout

If not, you can use expect, or just yes, to fake user interaction.

share|improve this answer
add comment

Without knowing what you're trying to do I'd argue you should be writing the script so that you always know if it's going to ask for stdin or not. Either that or pipe something into the command that's likely to be wanting something from stdin, but that's probably not the best idea.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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