私は反対のことをしようとしています
Stdoutでパイプを検出するために出力形式を変更するアプリケーションを実行していますが、リダイレクト時に同じ出力が得られるように、対話式ターミナルであると考えてほしいです。
expect
スクリプトでラッピングするか、PHPでproc_open()
を使用するとうまくいくと思っていましたが、そうではありません。
アイデアはありますか?
あぁ!
script
コマンドは、必要なことを行います...
script --return --quiet -c "[executable string]" /dev/null
トリックをします!
Usage:
script [options] [file]
Make a TypeScript of a terminal session.
Options:
-a, --append append the output
-c, --command <command> run command rather than interactive Shell
-e, --return return exit code of the child process
-f, --flush run flush after each write
--force use output file even when it is a link
-q, --quiet be quiet
-t[<file>], --timing[=<file>] output timing data to stderr or to FILE
-h, --help display this help
-V, --version display version
クリスの解 に基づいて、次の小さなヘルパー関数を思い付きました。
faketty() {
script -qfc "$(printf "%q " "$@")" /dev/null
}
風変わりなprintf
は、$@
内のスクリプトの引数を正しく展開し、コマンドの引用部分を保護するために必要です(以下の例を参照)。
使用法:
faketty <command> <args>
例:
$ python -c "import sys; print sys.stdout.isatty()"
True
$ python -c "import sys; print sys.stdout.isatty()" | cat
False
$ faketty python -c "import sys; print sys.stdout.isatty()" | cat
True
PHPから実行できるかどうかはわかりませんが、TTYを確認するために子プロセスが本当に必要な場合は、 [〜#〜] pty [〜#〜] を作成できます。
Cで:
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <unistd.h>
#include <pty.h>
int main(int argc, char **argv) {
int master;
struct winsize win = {
.ws_col = 80, .ws_row = 24,
.ws_xpixel = 480, .ws_ypixel = 192,
};
pid_t child;
if (argc < 2) {
printf("Usage: %s cmd [args...]\n", argv[0]);
exit(EX_USAGE);
}
child = forkpty(&master, NULL, NULL, &win);
if (child == -1) {
perror("forkpty failed");
exit(EX_OSERR);
}
if (child == 0) {
execvp(argv[1], argv + 1);
perror("exec failed");
exit(EX_OSERR);
}
/* now the child is attached to a real pseudo-TTY instead of a pipe,
* while the parent can use "master" much like a normal pipe */
}
しかし、実際には expect
自体がPTYを作成するという印象を受けました。
以前の回答を参照すると、Mac OS Xでは、「スクリプト」は次のように使用できます...
script -q /dev/null commands...
しかし、戻りコードが「\ n」から「\ r\n」に変わる可能性があるため、このように実行する必要がありました。
script -q /dev/null commands... | Perl -pe 's/\r\n/\n/g'
これらのコマンド間にパイプがある場合、stdoutをフラッシュする必要があります。例えば:
script -q /dev/null commands... | Ruby -ne 'print "....\n";STDOUT.flush' | Perl -pe 's/\r\n/\n/g'
特定の答えについてコメントするにはあまりにも新しいですが、最近助けてくれたので、上記のingomueller-netが投稿したfaketty
関数をフォローアップしたいと思いました。
これは、私が欲しくない/必要のないTypeScript
ファイルを作成しているので、スクリプトのターゲットファイルとして/ dev/nullを追加しました。
function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }
shellcheck <file> | less
を実行しているときに色を取得しようとしていたので、上記の答えを試しましたが、テキストが本来あるべき位置から水平方向にオフセットされるという奇妙な効果を生み出します。
In ./all/update.sh line 6:
for repo in $(cat repos); do
^-- SC2013: To read lines rather than words, pipe/redirect to a 'while read' loop.
(shellcheckに不慣れな人のために、警告のある行は問題のある場所に並ぶことになっています。)
上記の回答がshellcheckで動作するように、コメントのオプションの1つを試しました。
faketty() {
0</dev/null script -qfc "$(printf "%q " "$@")" /dev/null
}
これは動作します。また、--return
を追加し、長いオプションを使用して、このコマンドをわかりにくくしました。
faketty() {
0</dev/null script --quiet --flush --return --command "$(printf "%q " "$@")" /dev/null
}
BashおよびZshで動作します。
また、「UNIX環境での高度なプログラミング、第2版」という本のサンプルコードに含まれているptyプログラムもあります。
Mac OS Xでptyをコンパイルする方法は次のとおりです。