응용 프로그램에서 stdout을 파이프가 아닌 터미널로 생각하도록 속이는 무엇입니까?
"Detect if stdin is terminal or pipe?"와 반대로 하려고 합니다.
STDOUT에서 파이프를 검출하기 때문에 출력 포맷을 변경하는 어플리케이션을 실행하고 있으며 리다이렉트 시 동일한 출력을 얻을 수 있도록 인터랙티브 단말기로 간주하고 싶습니다.
제 생각엔 그걸 싸서expect
스크립트 작성 또는 사용proc_open()
PHP에서는 가능하지만 그렇지 않습니다.
뭐 좋은 생각 있어?
아하!
그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
Expect와 함께 제공되는 unbuffer 스크립트로 이 문제가 해결됩니다.그렇지 않은 경우, 애플리케이션은 TERM 환경 변수가 설정되어 있는 것 등, 출력의 접속처 이외의 것을 참조하고 있을 가능성이 있습니다.
Mac OS X에서는 이전 답변을 참조하여 다음과 같이 "스크립트"를 사용할 수 있습니다.
script -q /dev/null commands...
단, stdout에서 "\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 */
}
사실 그 자체가 PTY를 만든다는 인상을 받았어요.
Linux와 MacOs b 모두에서 a에 대한 @A-Ron의 응답 갱신은 (MacOs 이후) 상태 코드를 간접적으로 전파합니다.script
지원하지 않음)
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
}
예:
$ 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
구체적인 답변에 대해 언급하기엔 너무 새롭지만, 저는 그 질문에 대한 후속 조치를 취하려고 합니다.faketty
위의 ingomueller-net이 최근에 저를 도와준 이후 게시한 함수입니다.
이 때문에, 이 모든 것이typescript
원하지 않거나 필요 없는 파일을 스크립트 대상 파일로 /dev/null을 추가했습니다.
function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }
"유닉스 환경의 고급 프로그래밍, Second Edition"의 샘플 코드에는 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 *
나는 달릴 때 색을 얻으려고 했다.shellcheck <file> | less
Linux에서 위의 답변을 시도했지만 텍스트가 있어야 할 위치에서 수평으로 오프셋되는 기묘한 효과가 나타납니다.
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.
(셸 체크에 익숙하지 않은 경우 경고가 표시된 행은 문제가 있는 위치에 맞춰야 합니다).
위의 답변에 대해 셸체크를 사용하기 위해 댓글에서 다음 옵션 중 하나를 사용해 보았습니다.
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에서 작동합니다.
하이라이트를 있는 Ansible
output with with with로 출력합니다.tee
도 나의 입니다.
export ANSIBLE_FORCE_COLOR=True
언급URL : https://stackoverflow.com/questions/1401002/how-to-trick-an-application-into-thinking-its-stdout-is-a-terminal-not-a-pipe
'programing' 카테고리의 다른 글
SQLBulkCopy에 권장되는 배치 크기는 어떻게 됩니까? (0) | 2023.04.15 |
---|---|
데이터베이스가 현재 사용 중이므로 삭제할 수 없습니다. (0) | 2023.04.15 |
TabControl의 탭 항목 내 제어 상태를 유지하는 방법 (0) | 2023.04.15 |
AVFundation AVPlayer를 사용한 비디오 루프 (0) | 2023.04.15 |
WPF 사용자 제어에서 Import된 리소스와 로컬 리소스를 결합하는 방법 (0) | 2023.04.15 |