Linux 不会分配伪终端,因为 stdin 不是终端

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7114990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 05:45:42  来源:igfitidea点击:

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

linuxbashshellssh

提问by Matthew

I am trying to write a shell script that creates some directories on a remote server and then uses scp to copy files from my local machine onto the remote. Here's what I have so far:

我正在尝试编写一个 shell 脚本,在远程服务器上创建一些目录,然后使用 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

Whenever I run it I get this message:

每当我运行它时,我都会收到以下消息:

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

And the script just hangs forever.

脚本永远挂起。

My public key is trusted on the server and I can run all the commands outside of the script just fine. Any ideas?

我的公钥在服务器上是可信的,我可以很好地运行脚本之外的所有命令。有任何想法吗?

采纳答案by carok

Try ssh -t -t(or ssh -ttfor short) to force pseudo-tty allocation even if stdin isn't a terminal.

尝试ssh -t -t(或ssh -tt简称)强制伪 tty 分配,即使 stdin 不是终端。

See also: Terminating SSH session executed by bash script

另请参阅:终止由 bash 脚本执行的 SSH 会话

From ssh manpage:

从 ssh 联机帮助页:

-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.

回答by hmakholm left over Monica

I don't know where the hang comes from, but redirecting (or piping) commands into an interactive ssh is in general a recipe for problems. It is more robust to use the command-to-run-as-a-last-argument style and pass the script on the ssh command line:

我不知道挂起是从哪里来的,但是将(或管道)命令重定向到交互式 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'

(All in one giant '-delimited multiline command-line argument).

(全部包含在一个巨大的以'分隔符分隔的多行命令行参数中)。

The pseudo-terminal message is because of your -twhich asks ssh to try to make the environment it runs on the remote machine look like an actual terminal to the programs that run there. Your ssh client is refusing to do that because its ownstandard input is not a terminal, so it has no way to pass the special terminal APIs onwards from the remote machine to your actual terminal at the local end.

伪终端消息是因为您-t要求 ssh 尝试使其在远程机器上运行的环境看起来像在那里运行的程序的实际终端。您的 ssh 客户端拒绝这样做,因为它自己的标准输入不是终端,因此它无法将特殊终端 API 从远程机器向前传递到本地端的实际终端。

What were you trying to achieve with -tanyway?

-t无论如何,你想要达到什么目的?

回答by Andrew Prock

I'm adding this answer because it solved a related problem that I was having with the same error message.

我添加这个答案是因为它解决了一个相关的问题,我遇到了相同的错误消息。

Problem: I had installed cygwin under Windows and was getting this error: Pseudo-terminal will not be allocated because stdin is not a terminal

问题:我在 Windows 下安装了 cygwin 并收到此错误:Pseudo-terminal will not be allocated because stdin is not a terminal

Resolution: It turns out that I had notinstalled the openssh client program and utilities. Because of that cygwin was using the Windows implementation of ssh, not the cygwin version. The solution was to install the openssh cygwin package.

解决方案:事实证明我没有安装 openssh 客户端程序和实用程序。因为 cygwin 使用的是 ssh 的 Windows 实现,而不是 cygwin 版本。解决方案是安装 openssh cygwin 包。

回答by mxftw

ssh -tfoobar@localhost yourscript.pl

ssh -tfoob​​ar@localhost yourscript.pl

回答by Emil Bojda

Also with option -Tfrom manual

也可以-T手册中选择

Disable pseudo-tty allocation

禁用伪 tty 分配

回答by zanco

The warning message Pseudo-terminal will not be allocated because stdin is not a terminal.is due to the fact that no command is specified for sshwhile stdin is redirected from a here document. Due to the lack of a specified command as an argument sshfirst expects an interactive login session (which would require the allocation of a pty on the remote host) but then has to realize that its local stdin is no tty/pty. Redirecting ssh's stdin from a here document normally requires a command (such as /bin/sh) to be specified as an argument to ssh- and in such a case no pty will be allocated on the remote host by default.

警告消息Pseudo-terminal will not be allocated because stdin is not a terminal.是由于在ssh从 here 文档重定向 stdin 时未指定任何命令的事实。由于缺少指定的命令作为参数,ssh首先需要一个交互式登录会话(这将需要在远程主机上分配一个 pty),但随后必须意识到其本地 stdin 不是 tty/pty。ssh从 here 文档重定向的标准输入通常需要将命令(例如/bin/sh)指定为 - 的参数ssh,在这种情况下,默认情况下不会在远程主机上分配 pty。

Since there are no commands to be executed via sshthat require the presence of a tty/pty (such as vimor top) the -tswitch to sshis superfluous. Just use ssh -T user@server <<EOT ...or ssh user@server /bin/bash <<EOT ...and the warning will go away.

由于没有ssh需要通过tty/pty(例如vimtop)执行的命令,因此-t切换到ssh是多余的。只需使用ssh -T user@server <<EOT ...ssh user@server /bin/bash <<EOT ...,警告就会消失。

If <<EOFis not escaped or single-quoted (i. e. <<\EOTor <<'EOT') variables inside the here document will be expanded by the local shell before it is executing ssh .... The effect is that the variables inside the here document will remain empty because they are defined only in the remote shell.

如果<<EOF未转义或单引号(即<<\EOT<<'EOT')here 文档中的变量将在执行之前由本地 shell 展开ssh ...。结果是 here 文档中的变量将保持为空,因为它们仅在远程 shell 中定义。

So, if $REL_DIRshould be both accessible by the local shell and defined in the remote shell, $REL_DIRhas to be defined outside the here document before the sshcommand (version 1below); or, if <<\EOTor <<'EOT'is used, the output of the sshcommand can be assigned to REL_DIRif the only output of the sshcommand to stdout is genererated by echo "$REL_DIR"inside the escaped/single-quoted here document (version 2below).

因此,如果$REL_DIR既可以由本地 shell 访问又可以在远程 shell$REL_DIR中定义,则必须在ssh命令之前的 here 文档之外定义(下面的版本 1);或者,如果<<\EOT或者<<'EOT'被使用时,输出ssh命令可以被分配到REL_DIR如果唯一的输出ssh命令到标准输出由genereratedecho "$REL_DIR"内部逸出/单引号这里公开说明书(第2版下文)。

A third option would be to store the here document in a variable and then pass this variable as a command argument to ssh -t user@server "$heredoc"(version 3below).

第三种选择是将 here 文档存储在一个变量中,然后将此变量作为命令参数传递给ssh -t user@server "$heredoc"(下面的版本 3)。

And, last but not least, it would be no bad idea to check if the directories on the remote host were created successfully (see: check if file exists on remote host with ssh).

而且,最后但并非最不重要的是,检查远程主机上的目录是否已成功创建也不错(请参阅:使用 ssh 检查远程主机上是否存在文件)。

# 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"

回答by Dejay Clayton

Per zanco's answer, you're not providing a remote command to ssh, given how the shell parses the command line. To solve this problem, change the syntax of your sshcommand invocation so that the remote command is comprised of a syntactically correct, multi-line string.

根据zanco 的回答ssh鉴于 shell 如何解析命令行,您没有向 提供远程命令。要解决此问题,请更改ssh命令调用的语法,以便远程命令由语法正确的多行字符串组成。

There are a variety of syntaxes that can be used. For example, since commands can be piped into bashand sh, and probably other shells too, the simplest solution is to just combine sshshell invocation with heredocs:

可以使用多种语法。例如,由于命令可以通过管道传输到bashand sh,可能还有其他 shell,最简单的解决方案是将sshshell 调用与 heredocs结合起来:

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

Note that executing the above without/bin/bashwill result in the warning Pseudo-terminal will not be allocated because stdin is not a terminal. Also note that EOTis surrounded by single-quotes, so that bashrecognizes the heredoc as a nowdoc, turning off local variable interpolation so that the command text will be passed as-is to ssh.

请注意,在没有的情况下执行上述操作/bin/bash将导致警告Pseudo-terminal will not be allocated because stdin is not a terminal。还要注意的是EOT由单引号包围,使bash识别定界符作为nowdoc,关闭局部变量插值,因此命令文本将原样传递到ssh

If you are a fan of pipes, you can rewrite the above as follows:

如果你是管道的粉丝,你可以将上面的内容改写如下:

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

The same caveat about /bin/bashapplies to the above.

同样的警告/bin/bash也适用于上述情况。

Another valid approach is to pass the multi-line remote command as a single string, using multiple layers of bashvariable interpolation as follows:

另一种有效的方法是将多行远程命令作为单个字符串传递,使用多层bash变量插值,如下所示:

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

The solution above fixes this problem in the following manner:

上面的解决方案通过以下方式解决了这个问题:

  1. ssh user@serveris parsed by bash, and is interpreted to be the sshcommand, followed by an argument user@serverto be passed to the sshcommand

  2. "begins an interpolated string, which when completed, will comprise an argument to be passed to the sshcommand, which in this case will be interpreted by sshto be the remote command to execute as user@server

  3. $(begins a command to be executed, with the output being captured by the surrounding interpolated string

  4. catis a command to output the contents of whatever file follows. The output of catwill be passed back into the capturing interpolated string

  5. <<begins a bash heredoc

  6. 'EOT'specifies that the name of the heredoc is EOT. The single quotes 'surrounding EOT specifies that the heredoc should be parsed as a nowdoc, which is a special form of heredoc in which the contents do not get interpolated by bash, but rather passed on in literal format

  7. Any content that is encountered between <<'EOT'and <newline>EOT<newline>will be appended to the nowdoc output

  8. EOTterminates the nowdoc, resulting in a nowdoc temporary file being created and passed back to the calling catcommand. catoutputs the nowdoc and passes the output back to the capturing interpolated string

  9. )concludes the command to be executed

  10. "concludes the capturing interpolated string. The contents of the interpolated string will be passed back to sshas a single command line argument, which sshwill interpret as the remote command to execute as user@server

  1. ssh user@server由 bash 解析,并被解释为ssh命令,后跟user@server要传递给ssh命令的参数

  2. "开始一个内插字符串,完成后,将包含一个要传递给ssh命令的参数,在这种情况下,它将被解释ssh为要执行的远程命令user@server

  3. $(开始一个要执行的命令,输出被周围的内插字符串捕获

  4. cat是输出任何文件内容的命令。的输出cat将被传递回捕获的内插字符串

  5. <<开始一个 bash heredoc

  6. 'EOT'指定heredoc 的名称是EOT。'EOT 周围的单引号指定应该将 heredoc 解析为nowdoc,这是一种特殊形式的 heredoc,其中内容不会被 bash 插入,而是以文字格式传递

  7. 即遇到之间的任何内容<<'EOT'<newline>EOT<newline>将附加到所述nowdoc输出

  8. EOT终止 nowdoc,导致创建一个 nowdoc 临时文件并传递回调用cat命令。cat输出 nowdoc 并将输出传递回捕获插值字符串

  9. )结束要执行的命令

  10. "结束捕获内插字符串。内插字符串的内容将ssh作为单个命令行参数传递回,ssh它将解释为要执行的远程命令user@server

If you need to avoid using external tools like cat, and don't mind having two statements instead of one, use the readbuilt-in with a heredoc to generate the SSH command:

如果您需要避免使用诸如 的外部工具cat,并且不介意使用两个语句而不是一个语句,请使用read带有 heredoc的内置工具来生成 SSH 命令:

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}"

回答by Miguel Rentes

I was having the same error under Windows using emacs 24.5.1 to connect to some company servers through /ssh:user@host. What solved my problem was setting the "tramp-default-method" variable to "plink" and whenever I connect to a server I ommit the ssh protocol. You need to have PuTTY's plink.exe installed for this to work.

我在 Windows 下使用 emacs 24.5.1 通过 /ssh:user@host 连接到一些公司服务器时遇到了同样的错误。解决我的问题是将“tramp-default-method”变量设置为“plink”,每当我连接到服务器时,我都会忽略 ssh 协议。您需要安装 PuTTY 的 plink.exe 才能使其工作。

Solution

解决方案

  1. M-x customize-variable (and then hit Enter)
  2. tramp-default-method (and then hit Enter again)
  3. On the text field put plink and then Apply and Save the buffer
  4. Whenever I try to access a remote server I now use C-x-f /user@host: and then input the password. The connection is now correctly made under Emacs on Windows to my remote server.
  1. Mx 自定义变量(然后按 Enter)
  2. tramp-default-method(然后再次按 Enter)
  3. 在文本字段上放置 plink,然后应用并保存缓冲区
  4. 每当我尝试访问远程服务器时,我现在都会使用 Cxf /user@host: 然后输入密码。现在可以在 Windows 上的 Emacs 下正确连接到我的远程服务器。

回答by Wadih M.

After reading a lot of these answers I thought I would share my resulting solution. All I added is /bin/bashbefore the heredoc and it doesn't give the error anymore.

在阅读了很多这些答案后,我想我会分享我的解决方案。我添加的所有内容都/bin/bash在 heredoc 之前,它不再给出错误。

Use this:

用这个:

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

Instead of this (gives error):

而不是这个(给出错误):

ssh user@machine <<'ENDSSH'
   hostname
ENDSSH

Or use this:

或者使用这个:

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

Instead of this (gives error):

而不是这个(给出错误):

ssh user@machine < run-command.sh

EXTRA:

额外

If you still want a remote interactive prompt e.g. if the script you're running remotely prompts you for a password or other information, because the previous solutions won't allow you to type into the prompts.

如果您仍然需要远程交互提示,例如,如果您远程运行的脚本提示您输入密码或其他信息,因为以前的解决方案不允许您输入提示。

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

And if you also want to log the entire session in a file logfile.log:

如果您还想将整个会话记录在一个文件中logfile.log

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

回答by mklement0

All relevant information is in the existing answers, but let me attempt a pragmatic summary:

所有相关信息都在现有答案中,但让我尝试一个务实的总结

tl;dr:

tl;博士:

  • DO pass the commands to run using a command-line argument:
    ssh jdoe@server '...'

    • '...'strings can span multiple lines, so you can keep your code readable even without the use of a here-document:
      ssh jdoe@server ' ... '
  • Do NOT pass the commands via stdin, as is the case when you use a here-document:
    ssh jdoe@server <<'EOF' # Do NOT do this ... EOF

  • 请务必使用命令行参数传递要运行的命令
    ssh jdoe@server '...'

    • '...'字符串可以跨越多行,因此即使不使用 here-document,您也可以保持代码可读:
      ssh jdoe@server ' ... '
  • 不要通过stdin传递命令,就像使用here-document 一样
    ssh jdoe@server <<'EOF' # Do NOT do this ... EOF

Passing the commands as an argument works as-is, and:

将命令作为参数传递按原样工作,并且:

  • the problem with the pseudo-terminal will not even arise.
  • you won't need an exitstatementat the end of your commands, because the session will automatically exit after the commands have been processed.
  • 甚至不会出现伪终端的问题。
  • 您不需要exit在命令末尾添加语句,因为在处理完命令后会话将自动退出。

In short: passing commands via stdinis a mechanism that is at odds with ssh's design and causes problems that must then be worked around.
Read on, if you want to know more.

简而言之:通过标准输入传递命令是一种与ssh的设计不一致的机制,会导致必须解决的问题。
如果您想了解更多信息,请继续阅读。



Optional background information:

可选的背景信息:

ssh's mechanism for accepting commands to execute on the target server is a command-line argument: the final operand (non-option argument) accepts a string containing one or more shell commands.

ssh接受命令在目标服务器上执行的机制是命令行参数:最终操作数(非选项参数)接受包含一个或多个 shell 命令的字符串。

  • By default, these commands run unattended, in an non-interactiveshell, without the use of a (pseudo) terminal (option -Tis implied), and the session automatically endswhen the last command finishes processing.

  • In the event that your commands require user interaction, such as responding to an interactive prompt, you can explicitly request the creation of a pty (pseudo-tty), a pseudo terminal, that enables interacting with the remote session, using the -toption; e.g.:

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

    • Note that the interactive readprompt only works correctly with a pty, so the -toption is needed.

    • Using a pty has a notable side effect: stdout and stderr are combinedand both reported via stdout; in other words: you lose the distinction between regular and error output; e.g.:

      • 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

  • 默认情况下,这些命令在非交互式shell 中无人值守地运行,不使用(伪)终端(-T隐含选项),并且会话在最后一个命令完成处理时自动结束

  • 如果您的命令需要用户交互,例如响应交互式提示,您可以明确请求创建一个pty (pseudo-tty),一个伪终端,使用该-t选项启用与远程会话的交互;例如:

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

    • 请注意,交互式read提示仅适用于 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

In the absence of this argument, sshcreates an interactiveshell- including when you send commands via stdin, which is where the trouble begins:

在没有这个参数的情况下,ssh创建一个交互式shell- 包括当你通过stdin发送命令时,这是问题开始的地方:

  • For an interactiveshell, sshnormally allocates a pty (pseudo-terminal) by default, exceptif its stdin is not connected to a (real) terminal.

    • Sending commands via stdin means that ssh's stdin is no longer connected to a terminal, so nopty is created, and sshwarnsyou accordingly:
      Pseudo-terminal will not be allocated because stdin is not a terminal.

    • Even the -toption, whose express purpose is to requestcreation of a pty, is notenough in this case: you'll get the same warning.

      • Somewhat curiously, you must then doublethe -toptionto force creation of a pty: ssh -t -t ...or ssh -tt ...shows that you really, really mean it.

      • Perhaps the rationale for requiring this very deliberate step is that things may not work as expected. For instance, on macOS 10.12, the apparent equivalent of the above command, providing the commands via stdin and using -tt, does notwork properly; the session gets stuck after responding to the readprompt:
        ssh -tt jdoe@server <<<'read -p "Enter something: "; echo "Entered: [$REPLY]"'

  • 对于交互式shell,ssh默认情况下通常会分配一个 pty(伪终端),除非其 stdin 未连接到(真实)终端。

    • 通过 stdin 发送命令意味着ssh的 stdin 不再连接到终端,因此不会创建 pty,并相应地ssh警告
      Pseudo-terminal will not be allocated because stdin is not a terminal.

    • 即使是-t选项,其明确目的是要求建立一个pty的,是足够在这种情况下:你会得到同样的警告。

      • 有点奇怪的是,您必须选项加倍-t以强制创建 pty:ssh -t -t ...ssh -tt ...表明您真的,真的是认真的

      • 可能需要这个非常深思熟虑的步骤的理由是事情可能不会按预期进行。例如,在MacOS 10.12,上述命令的表观当量,从而提供通过stdin的命令,并使用-tt,就不能正常工作; 响应read提示后会话卡住:
        ssh -tt jdoe@server <<<'read -p "Enter something: "; echo "Entered: [$REPLY]"'



In the unlikely event that the commands you want to pass as an argument make the command line too long for your system (if its length approaches getconf ARG_MAX- see this article), consider copying the code to the remote system in the form of a script first (using, e.g., scp), and then send a command to execute that script.

万一您想作为参数传递的命令使命令行对于您的系统来说太长(如果它的长度接近getconf ARG_MAX- 请参阅本文),请考虑首先以脚本的形式将代码复制到远程系统(使用,例如,scp),然后发送命令来执行该脚本。

In a pinch, use -T, and provide the commands via stdin, with a trailing exitcommand, but note that if you also need interactive features, using -ttin lieu of -Tmay not work.

在紧要关头,使用-T,并通过stdin提供命令,带有尾随exit命令,但请注意,如果您还需要交互功能,则使用-tt代替-T可能不起作用。