스크립트의 표준 출력을 tmux 세션에서 실행되는 다른 스크립트/명령의 표준 입력으로 리디렉션

스크립트의 표준 출력을 tmux 세션에서 실행되는 다른 스크립트/명령의 표준 입력으로 리디렉션

적응 중이에요마커스 뮐러의 답변 지난 주에 질문을 했습니다. 표준 출력을 tmux 세션으로 리디렉션하여 ANSI 이스케이프 시퀀스를 렌더링한 다음 창 렌더링을 스크립트의 실제 출력으로 캡처하는 스크립트입니다. stdout으로 직접 인쇄하여 동일한 결과를 얻을 수 있기 때문에 전혀 유용하지 않다는 것을 알고 있습니다. 그러나 이것은 더 복잡한 해석을 통해 코드를 더 큰 프로젝트로 가져오기 위한 데모일 뿐이며 다음 기능이 필요합니다.

#!/bin/zsh

tmpdir="$(mktemp -d)"
fifo="${tmpdir}/fifo"
mkfifo "$fifo"
tmux new-session -d -s aux "while true; do cat ${fifo}; done"

exec 3>&1 1>"$fifo"


echo foo
echo bar
tput home
echo -n b

exec 1>&3 3>&-

tmux capture-pane -t "aux" -p -S0 -E1
tmux kill-session -t aux
rm -rf $tmpdir

출력은 다음과 같습니다(그리고 그래야 합니다).

boo
bar

코드를 단순화하는 데 관심이 있습니다. 유지 관리해야 하는 FIFO 대신 사용할 수 있는 stdin 리디렉션과 관련된 트릭이 있습니까? 한 줄짜리 방법을 사용하여 모든 내용을 계속 인쇄하고 완료되면 세션을 자동으로 닫을 수 있습니까?

tmux 파이프 창, 버퍼, 전송 키 및 실행 쉘을 사용해 보았지만 작동하지 못했습니다. 특히 명령/스크립트를 실행하는 스크립트의 stdin이 아닌 콘솔에 명령을 작성하는 것처럼 세션이 stdin을 사용하는 경우

어떻게든 단순화해야 할 것 같은 느낌이 듭니다.

답변1

유지 관리해야 하는 FIFO 대신 사용할 수 있는 stdin 리디렉션과 관련된 트릭이 있습니까?

새 세션에 할당된 고유 창의 고유 창 내용을 묻습니다 tmux. tty그런 다음 인쇄하십시오.

#!/bin/zsh

tmux new-session -d -s aux 'tail -f /dev/null' || exit 1
tty="$(tmux display-message -p -t aux -F '#{pane_tty}')"

{
  echo foo
  echo bar
  TERM=tmux tput home
  echo -n b
} > "$tty"

tmux capture-pane -t aux -p -S0 -E1
tmux kill-session -t aux

tmux display-message -p일반적으로 말해서, 그것으로부터 정보를 얻는 것은 매우 유용합니다. 귀하의 경우에는 tty에 대한 정보를 직접 얻을 수 tmux new-session있으며 해당 변수는 필요하지 않습니다 tty. 리디렉션을 설정하기 위해 다음과 같은 예비 단계를 수행할 필요가 없습니다.

{...} >"$(tmux new-session -d -s aux -P -F '#{pane_tty}' 'tail -f /dev/null')" || exit

참고는 tail -f /dev/nulltmux 창을 "활성"으로 유지하는 명령일 뿐입니다. 스크립트는 명령에 아무 것도 보내려고 시도하지 않지만 올바른 tty에 인쇄합니다. 이 답변은 제목("tmux 세션 내에서 실행되는 다른 스크립트/명령의 표준 입력으로 스크립트의 표준 출력 리디렉션")을 다루지는 않지만 원하는 기능을 제공합니다.

답변2

정확히 무엇을 요구하시는지 잘 모르겠습니다. 이스케이프 시퀀스를 처리하기 위해 tmux를 사용한다는 개념을 받아들이지만 단지 FIFO를 제거하고 싶습니까?

원하는 결과물만 만들어 보세요tmux에서:

tmux new-session -d -s aux "echo foo; echo bar; tput home; echo -n b"

tmux capture-pane -t aux -p -S0 -E1
tmux kill-session -t aux

FIFO의 내용을 무시합니다.

$fifoPS 및  와 같은 쉘 변수를 인용해야 합니다 $tmpdir. 공백이 아닌 문자로 구성된 상수 문자열을 실제로 인용할 필요는 없습니다 "aux".

답변3

나는 당신이 그런 일을 할 수 없다고 생각합니다. tmux그렇게 하면 2(그리고 분리될 때 0, 1, 2) 이상으로 수신하는 모든 fd가 닫히기 때문입니다.

close_range(3, 4294967295, 0)출력에서 동등한 항목을 확인 하거나 소스에서 호출하세요.straceclosefrom(STDERR_FILENO + 1)

따라서 명명된 파이프나 환경 변수(NUL 문자는 포함하지 않음)를 통해 또는 소켓, 임시 파일, 공유 메모리에 의해 실행되는 셸 코드에 포함된 다른 방법으로 데이터를 전달해야 합니다. tmux둘 중 어느 것도 사실이 아닙니다. 더 간단하거나 더 안정적일 것입니다.

그러나 귀하의 접근 방식에는 많은 문제가 있습니다.

  • 고정된 세션 이름을 사용하고 있습니다. 이는 스크립트에 대한 두 호출이 동시에 실행되지 않는다는 것을 보장할 수 없으면 스크립트를 안정적으로 사용할 수 없음을 의미합니다. 세션 이름을 선택하고 tmux옵션을 통해 -P검색 할 수 있습니다 new-session.
  • 동기화는 수행하지 않습니다. 실행하면 완료되거나 시작된다는 capture-pane보장이 없습니다 cat. 창의 내용을 검색하면 tmux 세션을 종료하라고 지시하는 대신 루프 + 종료를 수행하게 됩니다.
  • $fifo새 세션에서 실행되는 셸 코드에 콘텐츠를 포함시킵니다. 환경 변수로 전달되는 것이 가장 좋습니다.
  • mktemp의 종료 상태를 확인하지 않았습니다 mkfifo.
  • tmux는 사용자의 데이터를 읽습니다 ~/.tmux.conf. 이는 처리를 방해할 수 있습니다.
  • 이것은 스크립트를 실행하는 호스트 터미널이 아니라 최종적으로 해석되는 터미널 에뮬레이터이기 때문에 TERM=tmux환경 tput(또는 zsh의 내장 동등 항목)으로 전달해야 하므로 이스케이프 시퀀스를 보내야 합니다.echotitmux그것오히려 호스트 터미널이 이해합니다.
  • 를 사용하면 -S0 -E1창의 처음 2개 표시 행만 캡처됩니다.
  • 호스트 터미널 창과 동일한 크기의 창을 생성하도록 tmux에 지시할 수 있습니다.
  • 출력이 한 화면에 맞지 않는 경우 스크롤백 버퍼의 내용을 가져올 수도 있습니다.

아마도 다음과 같을 것입니다.

#! /bin/zsh -

tmpdir=$(mktemp -d) || exit
trap 'rm -rf -- $tmpdir' EXIT INT TERM HUP QUIT

in=$tmpdir/in out=$tmpdir/out
mkfifo -- $in $out || exit
session=$(
  IN=$in OUT=$out tmux -f /dev/null new-session -PEd -x ${COLUMNS:-80} -y ${LINES:-24} '
    cat -- "$IN"
    echo done > "$OUT"
    read may_I_exit < "$IN"
    '
) || exit

cat "$@" > $in || exit

read can_I_retrieve_the_output < $out || exit
tmux capture-pane -t $session -pS-
echo you may exit > $in

예를 들면 다음과 같습니다.

$ (TERM=tmux; print -rln foo bar$terminfo[home]b) | ./capture | hexdump -C
00000000  62 6f 6f 0a 62 61 72 0a  0a 0a 0a 0a 0a 0a 0a 0a  |boo.bar.........|
00000010  0a 0a 0a 0a 0a 0a 0a 0a  0a 0a 0a 0a 0a 0a 0a 0a  |................|
*
00000040  0a 0a                                             |..|
00000042

(내 터미널 창의 높이가 60줄이므로 모두 0x0a(LF) 바이트에 유의하세요.)

(부인 성명:저는 tmux 사용자가 아니므로 이 작업을 수행하는 더 똑똑하고 정확한 방법이 있을 것입니다.)


1 이 기능에 관한 한 , 자체 에뮬레이션( )과 다른 이스케이프 시퀀스가 ​​있는 터미널을 home사용할 가능성이 없기 때문에 실제로 영향을 미칠 가능성은 거의 없습니다 .hometmux\e[H

관련 정보