私は現在、Fluke DewK 1620a温湿度計に接続し、デバイスから現在の温度と湿度の読み取り値を抽出するスクリプトを開発しようとしています。これらのデバイスにはネットワークポートがありますが、そのポートを受信するための共通プロトコルはありません。それらは生のTCP接続のみを許可します。 netcatとputtyを介してインタラクティブに接続し、コマンドを渡し、出力を受け取ります。 netcatを介してスクリプトを作成しようとしています。(「netcat経由でFluke 1620aでデータをキャプチャする」を参照)しかし、まったく動作しませんでした。それ以来、私はTCP接続で読み取り/書き込みのためにファイル記述子を開くBashの独自の機能を使用してタスクを実行できることを発見しました。これでデータをファイルに取り込むことができますが、おそらく非常に基本的な問題であることがわかっている問題で問題が発生しています。
#!/bin/bash
$host=1.2.3.4
$port=10001
$location=lab1
$log=${location}_DewK.log
$datetime=$(date +%F_%T)
exec 3<>/dev/tcp/${host}/${port}
echo -e "read?" >&3 # Sends the read? command to the Fluke.
printf ${datetime} >> ${log} # Inserts a timestamp to the log.
cat <&3 | tee -a ${log} & # Tee was the only way I could get it to log.
sleep 1 && pkill cat # The cat just hangs out there & will not end.
exec 3<&-
exec 3>&-
私はそれが醜いことを知っていますが、それをより効率的にする方法を見つけることができないようです。私の主な質問は次のとおりです。
- "cat<&3"はあらゆる種類の問題を引き起こす可能性があります。 EOFがないので永遠に停止します。私は読書を通してさまざまな方法を試しましたが、うまく動作しないようです。 「cat」はデータを抽出してファイルに書き込むことができる唯一の方法のようですが、センサーを排他するのを防ぐために「pkill」を使用する必要があります。
- 結果を$resultsのような変数として読みたいのですが、"cat"を使うとこれを達成できないようです。私は非常に単純なものを見逃していると思いますが、それを理解できないようです。
Flukeの出力は「76.05,56.3,72.89,59.0^M」と同じです。私はEOLを検出できないためだとは知っていますが、 "cat <&3"の後に新しい行を追加する方法がわかりません。結果は次のログです。
2014-11-26_07:09:03
75.75,56.4,72.53,59.7^M2014-11-26_07:09:05
75.75,56.4,72.54,59.7^M2014-11-26_07:09:07
75.75,56.4,72.53,59.7^M
私の目標は、実行するたびにログファイルの1行に「$ {datetime} - $ {results}」を書き込むことですが、行を結合する方法がわかりません。答えは私が使用できる変数に結果を入れることにあると思います。
私が受けることができる助けをいただきありがとうございます。私はマニュアルページ、bashドキュメント、ブログ記事、そしてもちろんこのウェブサイトを見ました。私がここで収集した情報が私がこの地径に至った唯一の理由です。私は単に私の深さから離れて衝突コースにいました。
答え1
read?
結果ごとに1つの結果を得るのか、それとも複数の結果を得るのかはわかりません。リクエスト - >答えを言われているようです。そして、16進ダンプや出力を提供したことはありませんが、行の終わりはDOS CR-LFやunix LFではなくただCRのようです。 (これが後でプロンプトがnetcatの出力を無視する理由です。)
私はマニュアルを見つけました: http://us.flukecal.com/literature/product-manuals/1620a-user%E2%80%99s-guide
CRで応答が終了したことを確認します。これはcatと同じ問題があるため、シェルで使用するのが痛みを伴いますtr '\r' '\n'
。 1行後に停止しません。
# read -d sets the delimiter.
# $'' is a special type of quoting where \r expands to a literal carriage return.
get_temp () { # io to fluke on FD 3
echo "read?" >&3
local resp
IFS= read resp -d $'\r' -u 3
printf '%s\n' "$resp"
}
exec 3<>"/dev/tcp/$host/$port"
while true; do # whole loop is redirected to log
temp="$( get_temp )"
printf '%s - %s\n' "$(date +%F_%T)" "$temp"
# or echo -n "$(date) - "; get_temp
sleep 1
done | tee -a "$log"
# or just >> "$log", and tail -f the log file when you want it on screen.
tr
またはCR - > LF変換を処理する実装:
exec 3<>"/dev/tcp/$host/$port"
(while echo 'read?';do sleep 1;done >&3) &
tr -d '\r' '\n' <&3 | IFS= while read temp; do
printf '%s - %s\n' "$(date +%F_%T)" "$temp"
done >> "$log"
これにより、毎秒コマンドを作成するサブシェルがバックグラウンドに配置されます。現在の時刻を受信した行にフォーマットするには、まだ読み取りループが必要です。 ^Cがサブシェルを殺すかどうかはわかりません。
ループ内に設定された変数は、ループの終了後には表示されません。パイプに入れたので、試してみたいなら。
これは古い質問なので、実際には実行しませんでした。文法的なエラーや間違いがある可能性があります。しかし、私は全体的なアイデアが正しいと確信しています。