web-dev-qa-db-ja.com

コマンドからのリアルタイム値の変化を示すBashスクリプト

Linuxマシンには、さまざまなセンサーの状態の数値を提供する一連のコマンドがあります。

これらのコマンドの呼び出しは、次のようなものです。

$ command1
5647
$ command2
76
$ command3
8754

これらの値はリアルタイムで変化し、そのうちの1つのステータスを確認するたびに、コマンドを再起動する必要があります...ハードウェアを操作するには両手が必要なので、これはあまり役に立ちません。

私の目標は、次のようにこれらのコマンドを呼び出して値を更新し続ける(リアルタイムで非同期に、またはx秒ごとに値を更新する)単純なBashスクリプトを作成することです。

$ ./myScript.sh
command1: x
command2: y
command3: z
command4: v

ここで、xyzおよびvは変化する値です。

バッシュはこれを簡単かつ効率的に可能にしますか?または、Pythonなどの別の言語で実行することを選択する必要がありますか?

UPDATE with more info:

私の現在のスクリプトは:

#!/bin/bash
echo "Célula calibrada: " $(npe ?AI1)
echo "Anemómetro: " $(npe ?AI2)
echo "Célula temperatura: " $(npe ?AI3)
echo "Célula temperatura: " $(npe ?AI4)

npeは、数値を返すコマンドの例です。私はこのような出力を期待します:

enter image description here

この出力は、コマンドwatch -n x ./myScript.sh、ここでxは秒の更新値です。次のようにスクリプトを編集すると、

#!/bin/bash
while sleep 1; do
   clear; # added to keep the information in the same line 
   echo "Célula calibrada: " $(npe ?AI1);
   echo "Anemómetro: " $(npe ?AI2);
   echo "Célula temperatura: " $(npe ?AI3);
   echo "Célula temperatura: " $(npe ?AI4);
done

迷惑なちらつきで出力が表示されます。

enter image description here

8
balon

Bashでリアルタイムソリューションを実装するのは難しいかもしれません。

watchを使用して、X秒に1回スクリプトを実行する多くの方法があります。あなたはすでにmyScript.sh利用可能です。 Xを必要な秒数に置き換えます。

  1. watch -n X ./myScript.sh

  2. while sleep X; do ./myScript.sh; done

    upd。時計をエミュレートするには、反復の合間に画面をクリアしたい場合があります。スクリプト内では、次のようになります。

    while sleep X; do 
       clear; 
       command1;
       command2;
    done
    
  3. 上記のオプションのいずれかをスクリプト自体に追加します。

11
rush

tput cup 0 0を使用して、画面の左上にカーソルを移動できます。 clear 1回。

#!/bin/bash
clear
while sleep 1; do
    tput cup 0 0
    printf "%21s %6d    \n" \
      "Célula calibrada: "   $(npe ?AI1) \
      "Anemómetro: "         $(npe ?AI2) \
      "Célula temperatura: " $(npe ?AI3) \
      "Célula temperatura: " $(npe ?AI4)
done
14
glenn jackman

ちらつきは、コマンドが値を返すのに少し時間がかかるためだと思います。これは私の通常の回避策です:

cmds(){
  echo "Célula calibrada: " $(npe ?AI1);
  echo "Anemómetro: " $(npe ?AI2);
  echo "Célula temperatura: " $(npe ?AI3);
  echo "Célula temperatura: " $(npe ?AI4);
}

while true; do
  out="$(cmds)"
  clear
  echo "$out"
  sleep 1
done

考えられるのは、可能な限り最後に画面をクリアすることです。

9
bxm

clearの直前ではなく直後にsleepを使用すると、出力をより簡単に読み取ることができます。

#!/bin/sh
while sleep 1
do
   clear
   echo "Célula calibrada: " $(npe ?AI1)
   echo "Anemómetro: " $(npe ?AI2)
   echo "Célula temperatura: " $(npe ?AI3)
   echo "Célula temperatura: " $(npe ?AI4)
done

ただし、ここではループを削除し、watchを使用してスクリプトを繰り返し実行します。これは、個々のツールのより柔軟な構成です。

5
Toby Speight

あなたは正確にbashでそれを行うことができます。それでもテキストが点滅している場合は、以前の回答を完全に読んでいないことになります。

画面をclearする必要がありますbefore後ではなく、新しい値をエコーし​​ます。

3
Paul_Pedant

あなたは:行を表示してから、次を表示するコマンドを実行します。

すべてのコマンドを実行し(ディスプレイに触れずに)、結果を4つの変数に保存してから、これらの4つの結果を一度にクリアして表示します。

自分のスクリプトを変更する場合は、次を試してください。

#!/bin/bash
while sleep 1; do
    # facultative?#  tput cup 0 0
    ccab="$(npe ?AI1)"
    cane="$(npe ?AI2)"
    ctemp="$(npe ?AI3)"
    ctemp2="$(npe ?AI4)"
    clear
    printf "%21s %6d    \n" \
      "Célula calibrada: "   "$ccab" \
      "Anemómetro: "         "$cane" \
      "Célula temperatura: " "$temp" \
      "Célula temperatura: " "$temp2"
done

ここでは、4つの要求の長い実行が表示を変更せずに行われ、表示は非常に迅速に更新され、4つの新しい値で一度に表示されます。

2
Olivier Dulac

すべてのコマンドをwhileループ内に配置して、スリープタイミングを設定できます。次の例では、2秒ごとにスリープします。したがって、dateコマンドは2秒ごとに実行されます

#!/bin/bash

while (true)
do
        echo "Date & Time : $(date)"
        sleep 2
done
2
Kamaraj

これはtputを使用して各行を個別に更新するため、ちらつきのない50行を実行します。これを証明するために、各行の間に0.01のスリープを入れました。

Arg yを指定してスクリプトを実行すると、ターミナルウィンドウがカーソルの配置に使用する例が表示されます。エコーでエスケープをハードコードしました。あなたのものは異なる場合があります。移植性のために、tputを使用してシーケンスを動的に生成する必要があります。パフォーマンスを得るには、アプリに必要なすべてのtputシーケンスを事前に取得し、シェルに格納する必要があります。また、固定テキストを一度配置したら、可変部分を変更するだけです。

画面位置はtput argsの(0、0)から始まることに注意してください。また、画面コマンドの先行ゼロは8進数として解釈されるため、printfを使用して可視の行番号を再フォーマットします。また、更新後にカーソルを邪魔にならないように((0,0)のように)移動することもできます。

#! /bin/bash

#.. See what a CUrsor Position is on the current terminal.
[[ "${1}" == y ]] && {
    for r in {0..19}; do
        tput cup ${r} 15 | od -An -t ax1
    done
    exit
}

tput clear

while sleep 1; do
    for k in {1..50}; do
        sleep 0.01
        RW=$( printf '%.2d' ${k} )
        TS=$(date "+%Y-%m-%d %H:%M:%S.%N")
        echo -n -e "\e[${k};1H${RW}  ${TS}"
    done
    echo -n -e "\e[52;1H"
done
2
Paul_Pedant

スリープ終了後、バックスペースをエコーし​​て値を再表示します。これは、エスケープコード、端末の幅と行を表示できる端末を使用していることを前提としていますが、クイックショットとして機能します。例: いくつかのプロセスが終了するのを待っている間にスピナーを表示する

1
Matthias Š

Bashでループを設定できます-構成はwhile true; do ....; done どこ ....はコマンドです。あなたはする必要があります Ctrl+C それを止める。

ループでスリープ状態にする必要があります。そうしないと、大声で叫んでCPU時間をすべて消費してしまいます。スリープまでの秒数は、現在の数値を取得することと出力が多すぎることの間の妥協です。

画面全体の出力を固定列でフォーマットする場合(printfコマンドを使用)、バリエーションを確認しやすくなります。

私はおそらくすべての出力をファイルに送信し(「完了」後のリダイレクト)、後で自由に調べたり、グラフ化したり、統計を行ったりすることができます。 tail -fコマンドを別のウィンドウで表示すると、ファイルに追加されている最新のデータが表示されるので、それを確認することができます。

データ間の間隔が重要な場合に備えて、dateコマンドをループに入れて、各行にタイムスタンプを付けることもできます。

骨にもっと肉が必要な場合は、もう一度投稿してください。

1
Paul_Pedant