Peregrine
Peregrine

Reputation: 367

Retrieving Output From A Command Streaming Information

That title is strained... difficult to describe my interest, even more so to do it in a pithy manner.


Thanks to the reply from akostadinov, I was relieved of my ignorance of stdin. Here is the solution. The original question follows the solution...

I always associate the pipe with output, as if it were a one sided connection. I used pipes to direct output.

But, of course, you are directing it somewhere and that place your piping it to is using it as input. This is the first time in a program I have used, or even thought to use, stdin.

stdin fixed the issue perfectly.

I was writing a naive program to turn my midi keyboard into a type keyboard input device. The program serves its purpose, especially now that I have the resource consumption running at zero, but the function of it turned out to be a way better idea than I had anticipated. Now I program with my electronic keyboard, and if I hit a snag or am just burned on repetitious code, I turn up the piano and just play until I am able to work again.

nutes...

#!/bin/bash

while [ 17 ]; do
olea=""

aseqdump -p 20 | {

while read line ; do

    a=($line)
    if [ "$olea" != "$line" ];then

        b=${a[5]}
        if [ $b ]; then
                        lenny=${#b}
                        last=${b:$lenny-1:$lenny}
                        if [ "$last" == "," ]; then
                            b=${b:0:$lenny-1}
                        fi
        fi
        c=${a[4]}
        case "$b" in

            #7h3 0c74v35
            "60") if [ "${a[2]}" == "on" ]; then `/home/pikey/./xsendkeycode 54 1`; else `/home/pikey/./xsendkeycode 54 0`;fi;; #echo -ne "c"; echo -ne "c">>textfile ;;
            "62") if [ "${a[2]}" == "on" ]; then `/home/pikey/./xsendkeycode 40 1`; else `/home/pikey/./xsendkeycode 40 0`;fi;; #echo -ne "d"; echo -ne "d">>textfile ;;
            "64")   if [ "$c" == "controller" ]; then 
                                valdue=${a[7]}
                                if [ "$valdue" == "127" ]; then 
                                    `/home/pikey/./xsendkeycode 62 1` #shft
                                else    
                                    `/home/pikey/./xsendkeycode 62 0` #shft
                                fi
                            else 
                                if [ "${a[2]}" == "on" ]; then 
                                    `/home/pikey/./xsendkeycode 26 1` 
                                else 
                                    `/home/pikey/./xsendkeycode 26 0`
                                fi
                                        #echo -ne "e"
                                        #echo -ne "e">>textfile 
                        fi;;
            "65") if [ "${a[2]}" == "on" ]; then `/home/pikey/./xsendkeycode 41 1`; else `/home/pikey/./xsendkeycode 41 0`;fi;; #echo -ne "f"; echo -ne "f">>textfile ;;
            "67") if [ "${a[2]}" == "on" ]; then `/home/pikey/./xsendkeycode 42 1`; else `/home/pikey/./xsendkeycode 42 0`;fi;; #echo -ne "g"; echo -ne "g">>textfile ;;
            "69") if [ "${a[2]}" == "on" ]; then `/home/pikey/./xsendkeycode 38 1`; else `/home/pikey/./xsendkeycode 38 0`;fi;; #echo -ne "a"; echo -ne "a">>textfile ;;
            "71") if [ "${a[2]}" == "on" ]; then `/home/pikey/./xsendkeycode 56 1`; else `/home/pikey/./xsendkeycode 56 0`;fi;; #echo -ne "b"; echo -ne "b">>textfile ;;




        esac
    fi

    olea="$line"

done
}
done

It makes for net positive distractions.


basically I am running a command called aseqdump. From the man page:

NAME
       aseqdump - show the events received at an ALSA sequencer port

SYNOPSIS
       aseqdump [-p client:port,...]

When running the program listens to a client and outputs the clients status.

In my usage I am listening to a midi device.

The output constantly refreshes.

I am trying to write a bash script that reads in the most recent line and works off the information from that last line.

How can I do this?

I have tried to set the output as a variable, but was having difficulty making this work the way I intended.

Then I piped the output to a file and read from the file, which worked fine but the file quickly filled up, so I tried to cat only the last ten lines of the file back into itself but this crashed the pipe.

In the end I wrote a separate script that determines the number of lines in the output file, if it exceeds an upper limit it kills the process, cats the last ten lines into itself, then restarts the command with an appending pipe. Then it waits and does it again when needed.

This final method is just chewing up resources. About 8% when running and 17% and 14% when idling.

All I want is to read the latest output from a running command.

How can I do what I want to do without sucking up so much CPU?

Upvotes: 1

Views: 627

Answers (1)

akostadinov
akostadinov

Reputation: 18674

run your script like:

aseqdump | myscript.sh

Then stdin of your script process would be the output of aseqdump. Use the read bash built-in command to read lines from stdin. You would usually be something like that:

while read -r LINE; do
   <take action according to $LINE>
done

btw what your other approach does should not need so much CPU usage. Perhaps you are having a loop that executes too often. Perhaps if you insert a sleep time of say 1 second, then CPU will drastically decrease. Another possibility is that you're using some very inefficient way to do something but that can't be said without looking at the code.

Upvotes: 2

Related Questions