Pergunta

I have an external device that I need to power up and then wait for it to get started properly. The way I want to do this is by connecting to it via serial port (via Plink which is a command-line tool for PuTTY) and read all text lines that it prints and try to find the text string that indicates that it has been started properly. When that text string is found, the script will proceed.

The problem is that I need to read these text lines in real-time. So far, I have only seen methods for calling a command and then process its output when that command is finished. Alternatively, I could let Plink run in the background by appending an & to the command and redirecting the output to a file. But the problem is that this file will be empty from the beginning so the script will just proceed directly. Is there maybe a way to wait for a new line of a certain file and read it once it comes? Or does anyone have any other ideas how to accomplish this?

Here is the best solution I have found so far:

./plink "connection_name" > new_file &

sleep 10 # Because I know that it will take a little while before the correct text string pops up but I don't know the exact time it will take...

while read -r line
do
    # If $line is the correct string, proceed
done < new_file

However, I want the script to proceed directly when the correct text string is found.

So, in short, is there any way to access the output of a command continously before it has finished executing?

Foi útil?

Solução

This might be what you're looking for:

while read -r line; do
    # do your stuff here with $line
done < <(./plink "connection_name")

And if you need to sleep 10:

{
    sleep 10
    while read -r line; do
        # do your stuff here with $line
    done
} < <(./plink "connection_name")

The advantage of this solution compared to the following:

./plink "connection_name" | while read -r line; do
    # do stuff here with $line
done

(that I'm sure someone will suggest soon) is that the while loop is not run in a subshell.

The construct <( ... ) is called Process Substitution.

Hope this helps!

Outras dicas

Instead of using a regular file, use a named pipe.

mkfifo new_file

./plink "connection_name" > new_file &

while read -r line
do
    # If $line is the correct string, proceed
done < new_file

The while loop will block until there is something to read from new_file, so there is no need to sleep.

(This is basically what process substitution does behind the scenes, but doesn't require any special shell support; POSIX shell does not support process substitution.)

Newer versions of bash (4.2 or later) also support an option to allow the final command of a pipeline to execute in the current shell, making the simple solution

shopt +s lastpipe
./plink "connection_name" | while read -r line; do
    # ...
done

possible.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top