我正试图做相反的事情
我正在运行一个正在更改其输出格式的应用程序,因为它检测到stdout上的管道,我希望它认为它是一个交互式终端,以便在重定向时获得相同的输出.
我当时认为将它包装在expect
脚本中或使用proc_open()
PHP中的它会这样做,但事实并非如此.
有什么想法吗?
小智 167
啊哈!
该script
命令的作用,我们想要什么?
script --return --quiet -c "[executable string]" /dev/null
Run Code Online (Sandbox Code Playgroud)
诀窍!
ing*_*net 56
根据Chris的解决方案,我提出了以下小助手功能:
faketty() {
script -qfc "$(printf "%q " "$@")" /dev/null
}
Run Code Online (Sandbox Code Playgroud)
古怪的看printf
是要正确扩大在脚本的参数$@
,同时保护命令的可能引述部分(见下面的例子).
用法:
faketty <command> <args>
Run Code Online (Sandbox Code Playgroud)
例:
$ 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
Run Code Online (Sandbox Code Playgroud)
eph*_*ent 16
我不知道它是否可以通过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 */
}
Run Code Online (Sandbox Code Playgroud)
实际上我的印象是expect
它本身确实创造了一个PTY.
Tsu*_*oka 15
参考上一个答案,在Mac OS X上,"脚本"可以像下面这样使用......
script -q /dev/null commands...
Run Code Online (Sandbox Code Playgroud)
但是,因为它可能会将返回代码从"\n"更改为"\ r \n",所以我需要像这样运行.
script -q /dev/null commands... | perl -pe 's/\r\n/\n/g'
Run Code Online (Sandbox Code Playgroud)
如果这些命令之间存在某些管道,则需要刷新stdout.例如:
script -q /dev/null commands... | ruby -ne 'print "....\n";STDOUT.flush' | perl -pe 's/\r\n/\n/g'
Run Code Online (Sandbox Code Playgroud)
Jon*_*lin 10
更新@A-Ron 的答案 a) 在 Linux 和 MacOs 上工作 b) 间接传播状态代码(因为 MacOsscript
不支持它)
faketty () {
# Create a temporary file for storing the status code
tmp=$(mktemp)
# Ensure it worked or fail with status 99
[ "$tmp" ] || return 99
# Produce a script that runs the command provided to faketty as
# arguments and stores the status code in the temporary file
cmd="$(printf '%q ' "$@")"'; echo $? > '$tmp
# Run the script through /bin/sh with fake tty
if [ "$(uname)" = "Darwin" ]; then
# MacOS
script -Fq /dev/null /bin/sh -c "$cmd"
else
script -qfc "/bin/sh -c $(printf "%q " "$cmd")" /dev/null
fi
# Ensure that the status code was written to the temporary file or
# fail with status 99
[ -s $tmp ] || return 99
# Collect the status code from the temporary file
err=$(cat $tmp)
# Remove the temporary file
rm -f $tmp
# Return the status code
return $err
}
Run Code Online (Sandbox Code Playgroud)
例子:
$ faketty false ; echo $?
1
$ faketty echo '$HOME' ; echo $?
$HOME
0
embedded_example () {
faketty perl -e 'sleep(5); print "Hello world\n"; exit(3);' > LOGFILE 2>&1 </dev/null &
pid=$!
# do something else
echo 0..
sleep 2
echo 2..
echo wait
wait $pid
status=$?
cat LOGFILE
echo Exit status: $status
}
$ embedded_example
0..
2..
wait
Hello world
Exit status: 3
Run Code Online (Sandbox Code Playgroud)
小智 7
对于具体答案的评论太新了,但我想我会跟进faketty
ingomueller-net发布的功能,因为它最近帮助了我.
我发现这是创建一个typescript
我不想要/不需要的文件所以我添加了/ dev/null作为脚本目标文件:
function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }