すべてのシェルスクリプト出力を端末とログファイルに追加する*入力したテキストに送信する方法はありますか?

すべてのシェルスクリプト出力を端末とログファイルに追加する*入力したテキストに送信する方法はありますか?

シェルスクリプトの出力(ユーザーが入力したテキストを含む)を端末とログファイルに送信したいと思います。

tee私はとの任意の組み合わせがトリックを行うことができると思いますexecが、これまで運はありませんでした。teeユーザーが端末に入力した内容を自分でエコーしてキャプチャできることがわかります。

$ tee logfile
Hello  (I entered this at runtime)
Hello  (I entered this at runtime)
^C

$ cat logfile
Hello  (I entered this at runtime)

ただし、シェルスクリプトで呼び出されたコマンドに応答して、ユーザーが入力した内容を端末とログファイルの両方で確認する必要があります。

tee絶えずできないようです。

例えば:

$ read message 2>&1 | tee logfile
Hello  (I entered this at runtime)

$ cat logfile

そこには何も捉えられませんでした。Hello (I entered this at runtime)以前のようにファイルとして見ることができたらと思います。

また、次のようなシェルスクリプトにまとめてみましたteeexec

$ cat test.bash
#!bin/bash
# Note: in this simplified version of this file, I’m not looking at $1, $2, or anything else passed in, but will need to eventually

rm -f logfile
exec &> >(tee -a logfile)
echo “Say \”Hello\”” 2>&1
read -p “> “ 2>&1

残念ながら追加exec:

$ ./test.bash
Say “Hello”
> Hello  (I entered this at runtime)

$ cat logfile
Say “Hello”
> 

echoご覧のとおり、コマンドとコマンドの出力はキャプチャしますreadが、コマンドに応答して端末に入力した内容はキャプチャしませんread

それを行う方法はありますか?

私はscriptコマンド("make typescript of Terminal session")が画面上のすべてをキャプチャしてログファイルに保存することを知っています。ただし、scriptコマンドはシェルスクリプトで便利な方法で呼び出すことはできません。 (できますか?)

scriptまず呼び出す必要があり、次にユーザーは必要なシェルスクリプトを呼び出す必要があります。しかし、私はユーザーがコマンドとその引数を呼び出し、そのコマンドが他のすべてを実行し、すべてを記録するようにしたいと思います。

これにより、スクリプトがキャプチャしたすべての「追加」情報(カラーコード、バックスペースキーなど)があるため、テキストエディタで結果ログファイルを読み取ることが困難になります。

ログファイルで「人が読める」文字を見たいです。ユーザーがスペルエラーを修正したことを確認したくありません。編集を終えてEnterキーを押したときに「Hello」が画面に表示されるのを見たいです。キャプチャ後に追加情報が削除される可能性があると思います。

答え1

script少なくとも実装はutil-linuxスクリプト可能です。

たとえば、次のようにできます。

SHELL=/bin/sh script -qec '
  # any sh code here
  echo Whatever
  cat # user input' file.log

file.log以下を含む端末に記録されているすべての内容をキャプチャします。エコあなたが入力したもの。これには、LF から CRLF への変換などの tty 行規則によって実行される変換も含まれます。

scriptさらに一部追加

Script started on 2021-09-29 14:58:59+01:00 [TERM="screen.xterm-256color" TTY="/dev/pts/8" COLUMNS="191" LINES="54"]

ヘッダーと:

Script done on 2021-09-29 14:58:59+01:00 [COMMAND_EXIT_CODE="0"]

フッターは、kshスタイルのプロセス交換サポートを介してシェルから削除されます。以下を使用して削除できます。

SHELL=/bin/sh script -qec '...' >(sed '1d;$d' > file.log)

または、@zevzekが提案したように、scriptヘッダー/フッターを含むログに書き込むように指示し、/dev/null出力script-qヘッダーやフッターなし)をteeロギングにリダイレクトします。

(set -o pipefail; SHELL=/bin/sh script -qec '...' /dev/null | tee file.log)

zshまたはonを使用してmulti_ios(デフォルトでは):

SHELL=/bin/sh script -qec '...' /dev/null >&1 > file.log

擬似 tty 開始の tty 行ルールによる出力後処理を無効にするには、script次のように、少なくともホスト tty でこれを無効にし、NL -> CRNL 変換を再度有効にできます。

SHELL=/bin/sh HOST_TTY="$(tty)" script -qec '
  stty -opost && stty < "$HOST_TTY" opost onlcr || exit
  ...' file.log

(のコマンドが...この出力処理を復元しないとします。)

答え2

アプリケーションがttyデバイスに読み書きする内容を記録するもう1つの方法は、strace -P "$(tty)"ttyへのすべてのシステムコールを記録し、読み取りと書き込みの16進ダンプを含めることです。その後、xxdを使用してデコードできます。

strace -f -e read=all -e write=all \
       -e trace='read,write' \
       -P "$(tty)" \
       -e status=successful -o '|
          grep "^ "|cut -b11-60 | xxd -p -r > file.log
       ' -qqs0 -a0 cat

答え3

使用teeこの構文を使用してください。

read message
echo "${message}" | tee file

fileあなたのコメントが完了するまで、あなたのコメントがそこにあることを保証できます。

関連情報