スクリプトの実行中に標準入力(ユーザー入力)をキャプチャしてリダイレクトする

スクリプトの実行中に標準入力(ユーザー入力)をキャプチャしてリダイレクトする

次のように、スクリプト内のすべてのエントリに対してstdout / stderrをリダイレクトできます。

#!/bin/bash
exec > stdout_file
echo example

しかし、今ではスクリプト全体のstdinをファイルに書きたいと思います。私はこれを試しました:

#!/bin/bash
exec 0>stdin_file
sleep 5

sleepの実行中に「foo」と入力するとファイルに書き込まれませんが、bashはスクリプトの終了後に「foo」コマンドを実行しようとします。私は、これはbashがstdinをsleepのstdinにリンクしますが、sleepがstdinから読まないためだと思います。

私はすべてのユーザー入力がスクリプトコマンドの標準入力(ここでは「スリープ」と表示されている)に送信されるのではなく、ファイルにリダイレクトされることを望みます。

それ以外にも私も試してみました。

cat - >stdin_file &

しかし、bash は cats stdin をバックグラウンドで送信している間に接続を切断するので動作しません。

答え1

あなたの目標は何であるかよくわかりませんが、端末に入って対話的にコマンドを発行するのは少し難しいかもしれません。そのために設計されたツールは次のとおりです。スクリプト(1)、util-linuxから。

以下を含むファイルがあるとしますbridge.sh

#!/bin/sh
read -p "What… is your name? " NAME
read -p "What… is your quest? " QUEST
read -p "What… is your favourite colour? " COLOUR
echo "Go on. Off you go."

次のコマンドを使用してターミナルセッションをキャプチャできます。

script -c ./bridge.sh bridge_script

ユーザーの入力にのみ興味があるので、次のものを使用できます。

script -c ./bridge.sh --log-in bridge_input_script

マニュアルページ警告:

スクリプトは、改行やバックスペースを含むすべてをログファイルに入れます。これは素朴なユーザーが期待するものではありません。

実際には、入力ログに各入力の末尾にデフォルトのCRがあることがわかります。 (言葉になります。クリックするとCRが記録されます。)

> cat -A bridge_input_script
Script started on 2023-05-24 09:46:19-04:00 [TERM="xterm-256color" TTY="/dev/pts/4" COLUMNS="124" LINES="40"]$
My name is Sir Lancelot of Camelot.^MTo seek the Holy Grail.^MBlue.^M$
Script done on 2023-05-24 09:46:32-04:00 [COMMAND_EXIT_CODE="0"]$

(これは、計測中のコマンドについてもっと知らなくてもできる最善の方法です。)

今後の分析に必要なすべてのデータを取得するために通常行うことは次のとおりです。

script -c ./bridge.sh --log-timing bridge_timing_log --log-io bridge_io_log

私は使うスクリプト再生(1)再生セッション:

scriptreplay --log-io bridge_io_log --log-timing bridge_timing_log -m 0.01

(私は時間にあまり気にしないので、-m 0.01最大遅延時間を10msに制限します。)

script以下を含むいくつかの追加のヒントがあります。スクリプトライブ(1)、どちら実際にセッションを再実行してください。ログから。 (足に銃を撃つこともできます。RTFM、注意してください!)

答え2

#! /bin/bash -

tee input.log | {
  # contents of your script here
}

標準入力は保存され、中input.logかっこ内のコードに提供されます。コードはパイプの入力を表示し、これはttyデバイスの入力が必要な場合の動作に影響を与える可能性があります。

以下を使用して入力と出力を保存できます。

#! /bin/bash -
set -o pipefail
tee input.log | {
  # contents of your script here
} | tee output.log

pipefail何も見逃さないようteeに、またはパスワードただし、パイプライン内のシャットダウン状態にも影響を与えることに注意してください。パスワード)。

関連情報