コマンドをだまして、出力が端末に送信されると考えるようにする方法


38

出力が端末に送信されるときに動作を変更するコマンド(色付き出力の生成など)が与えられた場合、変更された動作を維持しながら、その出力をパイプラインでどのようにリダイレクトできますか?そのためのユーティリティが存在する必要がありますが、私は知りません。

などの一部のコマンドにはgrep --color=always、動作を強制するオプションフラグがありますが、問題は出力ファイル記述子のテストのみに依存するプログラムの回避方法です。

問題があれば、私のシェルはbashLinux上にあります。


コマンドがどのように出力ファイル記述子をテストし、どういうわけか出力端末から見られる結果と一致する結果を返す方法を知る必要があります。
アンドリューヘンレ

回答:


21

を使用して、必要なものを取得できますunbuffer

unbufferあるtcl/ expectスクリプトが。必要に応じてソースを見てください。manのCAVEATSセクションにも注意してください。

また、次のようなエイリアスは実行しないことに注意してください。

alias ls='ls --color=auto'

StéphaneChazelasが指摘したトリックを追加しない限り:

あなたが行う場合alias unbuffer='unbuffer '(末尾のスペースに注意)、その後、エイリアスは後に展開されますunbuffer


確認されたエイリアスに関する注意–ビルトインや関数のような他のシェル構成体でも動作しません。
アミール

4
あなたが行う場合alias unbuffer='unbuffer '(末尾のスペースに注意)、その後、エイリアスは後に展開されますunbuffer
ステファンシャゼル

unbufferそうです!sudo apt install expect-それは不明瞭でした。
loxaxs

22

ツールセットの歴史

あなたはそのようなツールが欲しい最初の人ではありません。人々はこのようなツールを30年もの間望んでいました。そして、それらもほぼその間存在していました。

この種の最も初期のツールは、ダニエルJ.バーンスタインの「pty」パッケージで、リッチザルツによって「ギンスナイフ」と記述されていました。「pty」パッケージのバージョン4は、1992年に発行されましたcomp.sources.unix(ボリューム25号127〜135)。World Wide Web上で引き続き検索可能です。ポール・ビクシーは当時それについて次のように説明しています。

何と言えばいい?スライスし、さいの目に切り、皿を洗い、犬を散歩させます。それは「うまくいく」、つまり、指示に従えば、髪を引っ張ったり、歯を噛んだり、他の標準的な移植作業をすることなく作業パッケージを手に入れることができます。

バーンスタインは、1999-04-07以前にこれを「ptyget」パッケージで更新しました。

新しい疑似ttyアロケーター、ptygetを作成しました。アルファ版はにありftp://koobera.math.uic.edu/pub/software/ptyget-0.50.tar.gzます。ptygetメーリングリストがあります。参加するには、空のメッセージをに送信し djb-ptyget-requ...@koobera.math.uic.eduます。ptygetのインターフェイスをゼロから設計しました。ptyよりもはるかにモジュール化されています。基本的なptyインターフェースは、現在3つの部分に分割されています。

  • ptyget:小さな、低レベルのプログラム—パッケージ内で唯一のsetuidプログラム—新しい擬似ttyを割り当て、選択したプログラムに渡します
  • ptyspawn:疑似ttyの下で子プロセスを実行し、終了するのを待って停止を監視する別の小さなプログラム
  • ptyio:もう少しだけ大きい、データを前後に移動するプログラム

古いGinsuナイフptyは現在綴られていますptybandage、これはの同義語ですptyget ptyio -t ptyspawn; pty -d、ネットワークプログラムをpseudo-ttyにアタッチするためのスペルptyrunは、の同義語ですptyget ptyio ptyspawn。そして、nobufの同義語です ptyget ptyio -r ptyspawn -23x。セッション管理機能を別のパッケージに分割しました。

その別個のパッケージは「sess」パッケージでした。

ちなみに、「ptyget」は、Berstein自身の未公開の「redo」ビルドシステムの非常に初期のバージョンであり、公開されている数少ないインスタンスの1つを例示することで有名です。 dependonはの明確な前駆体redo-ifchangeです。

使用法

ptybandage

ptybandageログインセッションで通常人々が望むものです。主な使用例は、実際にシェルパイプラインにある場合でも、標準入力、出力、またはエラーが端末に接続されているかどうかに敏感なプログラムを作成したり、標準ファイル記述子をファイルにリダイレクトしたりすることです。

それは(もちろん、適切な外部コマンドでなければならない)を実行するコマンドを受け取り、それが標準入力、出力、およびエラーをに至るもの接続端子に接続されていることを考えているような方法でそれを実行するptybandageのを元の標準入力、出力、およびエラー。

ジョブ制御シェルで実行する際の微妙な問題を処理し、端末の停止文字ptybandageが停止するだけでなく、内部端末に接続されているプログラムの実行も停止するようにします。

ptyrun

ptyrun人々は通常、TCPネットワークサーバーに必要なものです。その主な使用例は、端末がセットアップされていないリモート実行環境であり、端末がない場合に希望どおりに動作しないプログラムを実行します。

ジョブ制御シェルの下で実行されることは想定されていません。実行中のコマンドが停止シグナルを受信した場合、単に再起動されます。

利用可能なツールセット

Dru Nelsonは、「pty」バージョン4と「ptyget」の両方を公開しています。

Paul Jarcは、オペレーティングシステムが実際に提供しなくなったオリジナルのオペレーティングシステム固有の疑似端末デバイスioctlを処理しようとする修正版のptygetを公開しています。

noshソースパッケージには、類似のスクリプトptybandangeptyrunスクリプトが付属しており、これらはLaurent Bercotのexeclineツールとnosh パッケージの独自の擬似端末管理コマンドを使用します。noshバージョン1.23以降、これらはnosh-terminal-extrasパッケージに事前パッケージされています。(以前のバージョンは、ソースからビルドした人にのみ提供していました。)

いくつかの例を使用します

ptybandageAIX上でJurjgen Oskamを使用して、ヒアドキュメントから入力を明示的に開いてパスワードプロンプトの制御端末を読み取るプログラムに入力します。

$ ptybandage dsmadmc << EOF> uit.txt
ヨスカム
パスワード
クエリセッション
クエリプロセス
終了する
EOF

Andy Bradfordはptyrun、デーモンツールとucspi-tcpの下でOpenBSD を使用bgplgshて、ネットワーク経由で対話型ルーター制御プログラムにアクセスできるようにし、端末と通信していると考えさせます。

#!/ bin / sh
exec 2>&1
exec envuidgid rviews tcpserver -vDRHl0 0 23 ptyrun / usr / bin / bgplgsh

参考文献


歴史の教訓をありがとう。しかし、あなたが提案するツールは最新のLinuxディストリビューションでは利用できないため、役に立たない。
アミール

4
多数のハイパーリンクと、ツールが最も確実利用できる場所に当てられた回答のセクション全体あります。
JdeBP

1
あなたの意見はexpect
CMCDragonkai

20

socatを使用して、ptyを接続した状態でプロセスを開始し、socatを取得してptyのもう一方の端をファイルに接続できます。どのAFAIUがまさにあなたが尋ねたものです:

socat EXEC:"my-command",pty GOPEN:mylog.log

このメソッドはisatty呼び出されたby my-commandを返しtrue、それだけに依存するプロセスは出力制御コードにだまされます。一部のプロセス(特にgrep)もTERM環境変数の値をチェックするため、次のように適切な値に設定する必要がある場合があります。"xterm"


13

KarlCによってSuper Userに投稿された素晴らしいソリューションもあります

小さな共有ライブラリをコンパイルします。

echo "int isatty(int fd) { return 1; }" | gcc -O2 -fpic -shared -ldl -o isatty.so -xc -

次に、このisatty(3)オーバーライドを動的にロードするようにコマンドに指示します。

LD_PRELOAD=./isatty.so mycommand

これは、そこにあるすべてのコマンドで機能するわけではなく、予期しない方法で一部を壊す可能性もありますが、ほとんどの場合はおそらく機能します。


2
MacOSユーザーの場合、次を使用して同じ動作を得ることができますDYLD_INSERT_LIBRARIES=./isatty.so DYLD_FORCE_FLAT_NAMESPACE=y mycommand
クリストファーシュロバ

12

使用してみてはscript(1)いかがですか?

例えば:

script -q -c 'ls -G' out_file

カラーコードを保存した状態でls出力をout_file保存します。


ここでは機能しません。色はどのように保存されますか?out_file色付きで出力するために使用するツールはありますか?
キラ

1
ANSIカラーエスケープシーケンスを使用してファイルを表示するには@Kiraを使用しますless -R。ただし、この場合、出力がパイプラインで継続されるようにしたかったのですが、最終的には最終的には端末で終了しました。cat説明のために使用すると、のようなものでscript -q -c 'ls -G' /dev/null | cattypescriptファイルを完全に抑制し、プログラムの出力のみを残します。
アミール

ファイルを作成しないようにするには、単純にダッシュを(使用し-て)script:exempleの出力ファイル、script -q -c 'ls -G' -
フランクリンピアット

0

@Amirの答えに基づいて、実行時にライブラリを生成して含めるスクリプトを次に示します。

#!/bin/bash
set -euo pipefail

function clean_up {
  trap - EXIT # Restore default handler to avoid recursion
  [[ -e "${isatty_so:-}" ]] && rm "$isatty_so"
}
# shellcheck disable=2154 ## err is referenced but not assigned
trap 'err=$?; clean_up; exit $err' EXIT HUP INT TERM

isatty_so=$(mktemp --tmpdir "$(basename "$0")".XXXXX.isatty.so)
echo "int isatty(int fd) { return 1; }" \
  | gcc -O2 -fpic -shared -ldl -o "$isatty_so" -xc -
# Allow user to SH=/bin/zsh faketty mycommand
"${SH:-$SHELL}" -c 'eval $@' - LD_PRELOAD="$isatty_so" "$@"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.