programing

stdin은 단말기가 아니기 때문에 의사 단말기는 할당되지 않습니다.

lovejava 2023. 4. 14. 20:52

stdin은 단말기가 아니기 때문에 의사 단말기는 할당되지 않습니다.

리모트 서버에 디렉토리를 작성하고 scp를 사용하여 로컬머신에서 리모트로 파일을 복사하는 셸 스크립트를 작성하려고 합니다.지금까지의 내용은 다음과 같습니다.

ssh -t user@server<<EOT
DEP_ROOT='/home/matthewr/releases'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR=$DEP_ROOT"/"$datestamp
if [ ! -d "$DEP_ROOT" ]; then
    echo "creating the root directory"
    mkdir $DEP_ROOT
fi
mkdir $REL_DIR
exit
EOT

scp ./dir1 user@server:$REL_DIR
scp ./dir2 user@server:$REL_DIR

실행할 때마다 다음 메시지가 나타납니다.

Pseudo-terminal will not be allocated because stdin is not a terminal.

그리고 그 대본은 영원히 지워지지 않아.

공용 키는 서버에서 신뢰할 수 있으며 스크립트 외부에서 모든 명령을 정상적으로 실행할 수 있습니다.좋은 생각 있어요?

★★를 해 보세요.ssh -t -t (오류)ssh -tt합니다.

다음 항목도 참조하십시오.bash 스크립트로 실행된 SSH 세션을 종료하는 중

ssh manpage에서:

-T      Disable pseudo-tty allocation.

-t      Force pseudo-tty allocation.  This can be used to execute arbitrary 
        screen-based programs on a remote machine, which can be very useful,
        e.g. when implementing menu services.  Multiple -t options force tty
        allocation, even if ssh has no local tty.

' ' '도 '-T매뉴얼에서

유사 TTY 할당 사용 안 함

Zanco의 답변에 따르면, 당신은 원격 명령을 제공하는 것이 아닙니다.ssh셸이 명령줄을 해석하는 방법을 나타냅니다.하려면 , 의 합니다.ssh명령어 호출을 사용하면 리모트명령어가 구문적으로 올바른 여러 줄 문자열로 구성됩니다.

이치노력하다들어 를 파이프로 할 수 에 명령어를 파이프로 연결할 수 있습니다.bash ★★★★★★★★★★★★★★★★★」sh 아마 일 거예요, 가장 은 그냥 하는 가장 간단한 해결책은 단지 결합하는 것입니다.ssh"CHANGE: "CHANGE MATHANGE:

ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

상기의 실행은, 다음과 같이 행해 주세요. /bin/bash.Pseudo-terminal will not be allocated because stdin is not a terminal또, ., 의, 의, . 、 。EOT로 둘러싸여 에, 「Single-Parament」는 「Single-Parament」를 참조해 주세요.bash명령 텍스트가 그대로 전달되도록 로컬 변수 보간 기능을 해제하여 nowdoc으로 인식합니다.ssh.

파이프의 팬인 경우는, 상기의 내용을 다음과 같이 고쳐 쓸 수 있습니다.

cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

대해서도 같은 이 있습니다./bin/bash상기에 적용됩니다.

하나의 하고 여러 1을 입니다.bash변수 보간은 다음과 같습니다.

ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"

위의 솔루션은 다음 방법으로 이 문제를 해결합니다.

  1. ssh user@serverbash에 되며 bash로 됩니다.ssh.user@serverssh

  2. " 문자열을 가 "보간된 문자열"로됩니다.이 문자열이 완성되면 인수는 에 전달되는 인수로 구성됩니다.ssh 이 는 '명령어()'로 해석됩니다.ssh user@server

  3. $(는 주변합니다.

  4. cat는 뒤에 오는 파일의 내용을 출력하는 명령어입니다.cat.

  5. <<맹렬히 공격하다

  6. 'EOT', 세레독의 EOT인 을 지정합니다. 따옴표 " " "'주변 EOT는 내용이 bash에 의해 보간되지 않고 오히려 리터럴 형식으로 전달되는 특수한 형태의 유전인 nowdoc으로 해석되어야 한다고 지정합니다.

  7. " " " 에 콘텐츠<<'EOT' ★★★★★★★★★★★★★★★★★」<newline>EOT<newline>됩니다.

  8. EOT하는 nowdoc nowdoc으로 .cat명령어를 입력합니다. cat interpolated stringnowdoc으로.

  9. )를 종료합니다.

  10. "보간 문자열 캡처를 종료합니다.보간된 문자열의 내용은 다음으로 돌아갑니다.ssh인수로 할 수 .ssh하여 ''로 합니다.user@server

하는 것을 입니다.cat두 대신 두 개의 문장이 있는 것도.readSSH를 사용하다

IFS='' read -r -d '' SSH_COMMAND <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

ssh user@server "${SSH_COMMAND}"

같은 에러메시지로 인해 발생했던 관련 문제를 해결했기 때문에 이 답변을 추가합니다.

문제:Windows에서 sygwin을 설치했는데 다음 오류가 발생하였습니다.Pseudo-terminal will not be allocated because stdin is not a terminal

해상도:알고 보니 openssh 클라이언트 프로그램과 유틸리티를 설치하지 않았습니다.그 때문에, sygwin 의 버전이 아니고, ssh 의 Windows 실장을 사용하고 있었습니다.해결책은 openssh cygwin 패키지를 설치하는 것이었습니다.

모든 관련 정보는 기존 답변에 포함되어 있지만, 실용적인 요약을 시도해 보겠습니다.

tl;dr:

  • DO명령줄 인수 사용하여 실행할 명령을 전달합니다.
    ssh jdoe@server '...'

    • '...' 문자열은 여러 행에 걸쳐 사용할 수 있으므로 여기서 나타내는 문자를 사용하지 않아도 코드를 읽을 수 있습니다.
      ssh jdoe@server ' ... '
  • 다음 문서를 사용하는 경우와 같이 명령어stdin을 통해 전달하지 마십시오.
    ssh jdoe@server <<'EOF' # Do NOT do this ... EOF

명령어인수로 전달하면 그대로 기능합니다.

  • 유사 단자의 문제는 발생하지 않습니다.
  • 명령어 처리 후 세션이 자동으로 종료되므로 명령어 종료 시 스테이트먼트가 필요하지 않습니다.

요컨대 stdin을 통해 명령어를 전달하는 메커니즘은ssh님의 설계로 인해 회피해야 할 문제가 발생하고 있습니다.
더 알고 싶다면 계속 읽어보세요.


옵션 배경 정보:

타겟 서버에서 실행하는 명령어를 받아들이는 메커니즘명령줄 인수입니다.최종 오퍼랜드(non-option 인수)는 1개 이상의 셸 명령어를 포함하는 문자열을 받아들입니다ssh.

  • 디폴트로는 이들 명령어는 (의사) 단말기를 사용하지 않고 비인터랙티브셸 내에서 무인실행되며(옵션은 암묵적) 마지막 명령어 처리가 완료되면 세션이 자동으로 종료됩니다.

  • 인터랙티브프롬프트에 대한 응답 등 사용자 조작이 필요한 명령어가 있는 경우 리모트세션과의 상호작용을 가능하게 하는 의사 단말기 pty(의사)의 작성을 명시적으로 요구할 수 있습니다.-t★★★★

    • ssh -t jdoe@server 'read -p "Enter something: "; echo "Entered: [$REPLY]"'

    • 한 「」는,read에 "pty"는 "pty"로 동작합니다.-t옵션이 필요합니다.

    • pty를 사용하면 stdout과 stderr이 결합되어 stdout을 통해 둘 다 보고됩니다.즉, 일반 출력과 오류 출력의 구별이 없어집니다.예를 들어 다음과 같습니다.

      • ssh jdoe@server 'echo out; echo err >&2' # OK - stdout and stderr separate

      • ssh -t jdoe@server 'echo out; echo err >&2' # !! stdout + stderr -> stdout

인수가 없는 경우,는 stdin을 통해 명령어를 송신하는 경우를 포함하여 인터랙티브셸을 만듭니다.이것이 문제의 발단이 됩니다.

  • 인터랙티브 쉘의 경우ssh는 통상 디폴트로 pty(표준 단말)를 할당합니다., 그 stdin이 (실제) 단말기에 접속되어 있지 않은 경우는 제외합니다.

    • stdin 경유로 명령어를 송신하는 것은 stdin이 단말기에 접속되어 있지 않기 때문에 pty가 작성되지 않으며 에 따라 경고가 표시됩니다.
      Pseudo-terminal will not be allocated because stdin is not a terminal.

    • 이 경우 pty 작성요청하는 것을 목적으로 하는 옵션충분하지 않습니다.같은 경고가 표시됩니다.

      • 조금 이상하게도 pty를 강제로 작성하려면 옵션을 두 로 해야 합니다.ssh -t -t ... ★★★★★★★★★★★★★★★★★」ssh -tt ...네가 정말 진심이라는 걸 보여주지

      • 아마도 이 매우 신중한 단계를 요구하는 이유는 일이 예상대로 작동하지 않을있기 때문일 것이다.예를 들어, macOS 10.12에서는 위의 명령어와 외관상 동등하며 stdin을 통해 명령어를 제공하고,-tt는 정상적으로 동작하지 않습니다.에 응답한 후 세션이 정지합니다.read★★★★★★★★★★★★★★★★★★:
        ssh -tt jdoe@server <<<'read -p "Enter something: "; echo "Entered: [$REPLY]"'


긴 )getconf ARG_MAX- 이 문서를 참조해 주세요.먼저 스크립트 형식으로 리모트시스템에 코드를 카피하는 것을 검토해 주세요(예를 들어,scp명령어를 전송하여 스크립트를 실행합니다.

경우, 하세요.-Tstdin을 통해 명령어를 입력합니다.exit한 경우, 「」, 「」를 해 주세요.-tt-T이치노

메시지 " " "Pseudo-terminal will not be allocated because stdin is not a terminal.입니다.ssh은 여기서 stdin에서 됩니다.ssh는 처음에 인터랙티브로그인 세션(리모트호스트상의 pty 할당이 필요)을 상정하고 있습니다만, 그 후 로컬 stdin이 tty/pty가 아님을 인식할 필요가 있습니다.ssh에는 보통, 「stdin」등)./bin/sh됩니다.ssh이 경우 디폴트로는 리모트호스트에 pty가 할당되지 않습니다.

를 통해 ssh의 (ttty/pty 등가:vim ★★★★★★★★★★★★★★★★★」top의 개요-t로로로 ssh사용하다, 사용하다ssh -T user@server <<EOT ... ★★★★★★★★★★★★★★★★★」ssh user@server /bin/bash <<EOT ...그러면 경고는 사라질 겁니다.

if<<EOF는, 싱글이 「스케이프」또는 「싱글<<\EOT ★★★★★★★★★★★★★★★★★」<<'EOT'된 후 ssh ...그 결과 이 문서 내의 변수는 리모트셸에만 정의되어 있기 때문에 비어 있습니다.

만약에 '만약에'가$REL_DIR되어 있어야 .$REL_DIR는 이 .ssh명령어(아래 버전1) 또는<<\EOT ★★★★★★★★★★★★★★★★★」<<'EOT'의 됩니다.ssh는 「어느 쪽인가」에 할 수 .REL_DIR" " 의 한 ssh는 stdout에 의해 된다.echo "$REL_DIR"(아래 버전 2)에 기재되어 있습니다.

이후 이 입니다.ssh -t user@server "$heredoc"(아래 버전 3)

마지막으로 리모트호스트의 디렉토리가 정상적으로 작성되었는지 확인하는 것도 나쁘지 않습니다(「sh」를 사용하는 리모트호스트에 파일이 존재하는지 확인」을 참조).

# version 1

unset DEP_ROOT REL_DIR
DEP_ROOT='/tmp'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR="${DEP_ROOT}/${datestamp}"

ssh localhost /bin/bash <<EOF
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
#echo "$REL_DIR"
exit
EOF

scp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"


# version 2

REL_DIR="$(
ssh localhost /bin/bash <<\EOF
DEP_ROOT='/tmp'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR="${DEP_ROOT}/${datestamp}"
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
echo "$REL_DIR"
exit
EOF
)"

scp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"


# version 3

heredoc="$(cat <<'EOF'
# -onlcr: prevent the terminal from converting bare line feeds to carriage return/line feed pairs
stty -echo -onlcr
DEP_ROOT='/tmp'
datestamp="$(date +%Y%m%d%H%M%S)"
REL_DIR="${DEP_ROOT}/${datestamp}"
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
echo "$REL_DIR"
stty echo onlcr
exit
EOF
)"

REL_DIR="$(ssh -t localhost "$heredoc")"

scp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"

행의 원인은 알 수 없지만 명령어를 인터랙티브한 ssh로 리다이렉트(또는 파이핑)하는 것은 일반적으로 문제의 원인입니다.command-to-run-as-a-last-argument 스타일을 사용하여 ssh 명령줄에서 스크립트를 전달하는 것이 보다 견고합니다.

ssh user@server 'DEP_ROOT="/home/matthewr/releases"
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR=$DEP_ROOT"/"$datestamp
if [ ! -d "$DEP_ROOT" ]; then
    echo "creating the root directory"
    mkdir $DEP_ROOT
fi
mkdir $REL_DIR'

자이언트)'- intercredited multiline " " " " ) 。

는, 「의사 단말」의 「의사 단말」의 「 단말기는 「의사 단말」입니다.-t리모트 머신상에서 동작하는 환경을, 리모트 머신상에서 동작하는 프로그램의 실제의 단말기로서 인식하도록 ssh를 요구합니다.SSH 클라이언트는 자체의 표준 입력이 단말기가 아니기 때문에 리모트머신에서 로컬엔드의 실제 단말기에 특별한 단말기 API를 전달할 방법이 없기 때문에 이를 거부하고 있습니다.

당신은 무엇으로 달성하려고 했습니까?-t★★★★★★★★★★★★★★★★★?

이 답변들을 많이 읽고 그 결과 얻은 해결책을 공유해야겠다고 생각했습니다. 은 ★★★★★★★★★★/bin/bash유전자가 나오기 전에 더 이상 오류가 나지 않습니다.

사용방법:

ssh user@machine /bin/bash <<'ENDSSH'
   hostname
ENDSSH

대신 (오류 발생):

ssh user@machine <<'ENDSSH'
   hostname
ENDSSH

또는 다음을 사용합니다.

ssh user@machine /bin/bash < run-command.sh

대신 (오류 발생):

ssh user@machine < run-command.sh

추가:

리모트 인터랙티브프롬프트가 필요한 경우(예를 들어 리모트 실행 중인 스크립트에서 패스워드나 기타 정보를 입력하도록 요구하는 경우)는 이전 솔루션에서는 프롬프트에 입력할 수 없기 때문입니다.

ssh -t user@machine "$(<run-command.sh)"

, 는, 「」logfile.log:

ssh -t user@machine "$(<run-command.sh)" | tee -a logfile.log

Windows에서 emacs 24.5.1을 사용하여 /ssh:user@host를 통해 일부 회사 서버에 접속할 때 동일한 오류가 발생했습니다.문제를 해결한 것은 "tramp-default-method" 변수를 "plink"로 설정하고 서버에 연결할 때마다 ssh 프로토콜을 실행하는 것이었습니다.PuTTY의 플링크가 필요해요.exe 를 인스톨 해 주세요.

솔루션

  1. M-x customize-variable (다음 Enter 키를 누릅니다)
  2. tramp-default-method (다시 Enter 키를 누릅니다)
  3. 텍스트 필드에 plink를 입력한 후 Apply and Save the buffer를 입력합니다.
  4. 리모트 서버에 액세스 하려고 하면, C-x-f /user@host: 를 사용하고, 패스워드를 입력합니다.이것으로, Windows 의 Emacs 로 리모트 서버에의 접속이 올바르게 확립되었습니다.

언급URL : https://stackoverflow.com/questions/7114990/pseudo-terminal-will-not-be-allocated-because-stdin-is-not-a-terminal