「 Detect if stdin is terminal or pipe? 」の反対をやろうとしています。
STDOUT でパイプを検出したために出力形式を変更するアプリケーションを実行していますが、リダイレクト時に同じ出力が得られるように、対話型端末であると認識させたいと考えています。
expect
スクリプトでラップするかproc_open()
、PHP で a を使用するとうまくいくと思っていましたが、そうではありません。
そこに何かアイデアはありますか?
「 Detect if stdin is terminal or pipe? 」の反対をやろうとしています。
STDOUT でパイプを検出したために出力形式を変更するアプリケーションを実行していますが、リダイレクト時に同じ出力が得られるように、対話型端末であると認識させたいと考えています。
expect
スクリプトでラップするかproc_open()
、PHP で a を使用するとうまくいくと思っていましたが、そうではありません。
そこに何かアイデアはありますか?
あはは!
コマンドは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
Chris のソリューションに基づいて、次の小さなヘルパー関数を思い付きました。
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
以前の回答を参照すると、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'
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 を作成するという印象を受けました。
書籍「UNIX環境での高度なプログラミング 第2版」のサンプルコードにもptyプログラムが含まれています!
Mac OS X で pty をコンパイルする方法は次のとおりです。
man 4 pty # pty -- pseudo terminal driver
open http://en.wikipedia.org/wiki/Pseudo_terminal
# Advanced Programming in the UNIX Environment, Second Edition
open http://www.apuebook.com
cd ~/Desktop
curl -L -O http://www.apuebook.com/src.tar.gz
tar -xzf src.tar.gz
cd apue.2e
wkdir="${HOME}/Desktop/apue.2e"
sed -E -i "" "s|^WKDIR=.*|WKDIR=${wkdir}|" ~/Desktop/apue.2e/Make.defines.macos
echo '#undef _POSIX_C_SOURCE' >> ~/Desktop/apue.2e/include/apue.h
str='#include <sys/select.h>'
printf '%s\n' H 1i "$str" . wq | ed -s calld/loop.c
str='
#undef _POSIX_C_SOURCE
#include <sys/types.h>
'
printf '%s\n' H 1i "$str" . wq | ed -s file/devrdev.c
str='
#include <sys/signal.h>
#include <sys/ioctl.h>
'
printf '%s\n' H 1i "$str" . wq | ed -s termios/winch.c
make
~/Desktop/apue.2e/pty/pty ls -ld *