本文翻译自:Pseudo-terminal will not be allocated because stdin is not a terminal

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. 我正在尝试编写一个shell脚本,在远程服务器上创建一些目录,然后使用scp将文件从本地计算机复制到远程服务器上。 Here's what I have so far: 这是我到目前为止所拥有的:

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" ]; thenecho "creating the root directory"mkdir $DEP_ROOT
fi
mkdir $REL_DIR
exit
EOTscp ./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? 有任何想法吗?


#1楼

参考:https://stackoom.com/question/Tqvu/由于stdin不是终端-因此不会分配伪终端


#2楼

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 not installed the openssh client program and utilities. 解决方案 :事实证明我没有安装openssh客户端程序和实用程序。 Because of that cygwin was using the Windows implementation of ssh, not the cygwin version. 因为cygwin使用ssh的Windows实现,而不是cygwin版本。 The solution was to install the openssh cygwin package. 解决方案是安装openssh cygwin软件包。


#3楼

ssh -t foob​​ar @ localhost yourscript.pl


#4楼

Also with option -T from manual 还有手动选项-T

Disable pseudo-tty allocation 禁用伪tty分配


#5楼

The warning message Pseudo-terminal will not be allocated because stdin is not a terminal. Pseudo-terminal will not be allocated because stdin is not a terminal.警告消息Pseudo-terminal will not be allocated because stdin is not a terminal. is due to the fact that no command is specified for ssh while stdin is redirected from a here document. 是因为当从这里的文档重定向stdin时没有为ssh指定命令。 Due to the lack of a specified command as an argument ssh first 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. 由于缺少指定的命令作为参数, ssh首先需要一个交互式登录会话(这需要在远程主机上分配一个pty),但是必须意识到它的本地stdin不是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. 从here文档重定向ssh的stdin通常需要将命令(例如/bin/sh )指定为ssh的参数 - 在这种情况下,默认情况下不会在远程主机上分配pty。

Since there are no commands to be executed via ssh that require the presence of a tty/pty (such as vim or top ) the -t switch to ssh is superfluous. 由于没有要通过ssh执行的命令需要存在tty / pty(例如vimtop ),因此-t切换到ssh是多余的。 Just use ssh -T user@server <<EOT ... or ssh user@server /bin/bash <<EOT ... and the warning will go away. 只需使用ssh -T user@server <<EOT ...ssh user@server /bin/bash <<EOT ...并且警告将消失。

If <<EOF is not escaped or single-quoted (ie <<\\EOT or <<'EOT' ) variables inside the here document will be expanded by the local shell before it is executing ssh ... . 如果<<EOF未被转义或单引号(即<<\\EOT<<'EOT' ),则本地文档中的变量将在执行ssh ...之前由本地shell进行扩展。 The effect is that the variables inside the here document will remain empty because they are defined only in the remote shell. 结果是here文档中的变量将保持为空,因为它们仅在远程shell中定义。

So, if $REL_DIR should be both accessible by the local shell and defined in the remote shell, $REL_DIR has to be defined outside the here document before the ssh command ( version 1 below); 因此,如果$REL_DIR既可以由本地shell访问,也可以在远程shell中定义,则必须在ssh命令(下面的版本1 )之前在here文档之外定义$REL_DIR ; or, if <<\\EOT or <<'EOT' is used, the output of the ssh command can be assigned to REL_DIR if the only output of the ssh command to stdout is genererated by echo "$REL_DIR" inside the escaped/single-quoted here document ( version 2 below). 或者,如果使用<<\\EOT<<'EOT' ,则ssh命令的输出可以分配给REL_DIR如果stdout的ssh命令的唯一输出由转义/单个内的echo "$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 3 below). 第三种选择是将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 1unset 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" ]; thenecho "creating the root directory" 1>&2mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
#echo "$REL_DIR"
exit
EOFscp -r ./dir1 user@server:"$REL_DIR"
scp -r ./dir2 user@server:"$REL_DIR"# version 2REL_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" ]; thenecho "creating the root directory" 1>&2mkdir "$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 3heredoc="$(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" ]; thenecho "creating the root directory" 1>&2mkdir "$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"

#6楼

Per zanco's answer , you're not providing a remote command to ssh , given how the shell parses the command line. 根据zanco的回答 ,鉴于shell如何解析命令行,你不会向ssh提供远程命令。 To solve this problem, change the syntax of your ssh command invocation so that the remote command is comprised of a syntactically correct, multi-line string. 要解决此问题,请更改ssh命令调用的语法,以便远程命令由语法正确的多行字符串组成。

There are a variety of syntaxes that can be used. 可以使用各种语法。 For example, since commands can be piped into bash and sh , and probably other shells too, the simplest solution is to just combine ssh shell invocation with heredocs: 例如,由于命令可以通过管道传输到bashsh ,也可能是其他shell,最简单的解决方案是将ssh shell调用与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/bash will result in the warning Pseudo-terminal will not be allocated because stdin is not a terminal . 注意,执行上面没有 /bin/bash将导致警告Pseudo-terminal will not be allocated because stdin is not a terminal Also note that EOT is surrounded by single-quotes, so that bash recognizes the heredoc as a nowdoc , turning off local variable interpolation so that the command text will be passed as-is to ssh . 另请注意, EOT 被单引号括起来,因此bash将heredoc识别为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/bash applies to the above. 关于/bin/bash的相同警告适用于上述内容。

Another valid approach is to pass the multi-line remote command as a single string, using multiple layers of bash variable 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@server is parsed by bash, and is interpreted to be the ssh command, followed by an argument user@server to be passed to the ssh command ssh user@server由bash解析,并被解释为ssh命令,后跟一个参数user@server传递给ssh命令

  2. " begins an interpolated string, which when completed, will comprise an argument to be passed to the ssh command, which in this case will be interpreted by ssh to be the remote command to execute as user@server "开始一个内插字符串,在完成时,将包含一个要传递给ssh命令的参数,在这种情况下, ssh将被解释为要作为user@server执行的远程命令

  3. $( begins a command to be executed, with the output being captured by the surrounding interpolated string $(开始执行命令,输出由周围的插值字符串捕获

  4. cat is a command to output the contents of whatever file follows. cat是一个输出以下任何文件内容的命令。 The output of cat will be passed back into the capturing interpolated string cat的输出将被传递回捕获插值字符串

  5. << begins a bash heredoc <<开始一个bash heredoc

  6. 'EOT' specifies that the name of the heredoc is EOT. 'EOT'指定heredoc的名称是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 单引号'周围的EOT指定heredoc应该被解析为nowdoc ,这是一种特殊形式的heredoc,其中的内容不会被bash插值,而是以字面格式传递

  7. Any content that is encountered between <<'EOT' and <newline>EOT<newline> will be appended to the nowdoc output <<'EOT'<newline>EOT<newline>之间遇到的任何内容都将附加到nowdoc输出

  8. EOT terminates the nowdoc, resulting in a nowdoc temporary file being created and passed back to the calling cat command. EOT终止nowdoc,导致创建nowdoc临时文件并将其传递回调用cat命令。 cat outputs the nowdoc and passes the output back to the capturing interpolated string cat输出nowdoc并将输出传递回捕获插值字符串

  9. ) concludes the command to be executed )总结要执行的命令

  10. " concludes the capturing interpolated string. The contents of the interpolated string will be passed back to ssh as a single command line argument, which ssh will interpret as the remote command to execute as user@server "结束捕获插值字符串。插值字符串的内容将作为单个命令行参数传递回sshssh将解释为作为user@server执行的远程命令

If you need to avoid using external tools like cat , and don't mind having two statements instead of one, use the read built-in with a heredoc to generate the SSH command: 如果您需要避免使用像cat这样的外部工具,并且不介意使用两个语句而不是一个语句,请使用带有heredoc的read内置命令来生成SSH命令:

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

由于stdin不是终端,因此不会分配伪终端相关推荐

  1. linux的终端,网络虚拟终端,伪终端

    linux的终端,网络虚拟终端,伪终端 转自:http://www.xuebuyuan.com/877887.html Linux上许多网络服务应用,如l2tp.pptp.telnet,都用到了伪终端 ...

  2. linux中的伪终端编程,Linux中的伪终端编程 - 残剑_飞雪的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

    如何操作伪终端: 伪终端的使用是成对出现的,分为master 和 slaver 主设备:/dev/ptmx (i850上的主设备名) 从设备:动态生成:/dev/pts/0.......x 功能:写入 ...

  3. linux stdin shell,关于shell:如何在Alpine Linux中修复“因为stdin不是终端而不会分配伪终端”?...

    我正在编写一个运行各种shell命令的PHP程序.有时它需要调用su,并且根据设计,我希望它提示输入提升的特权密码.在PHP中使用passthru()可以很好地解决这个问题. 我选择只为我的程序编写功 ...

  4. 终端、虚拟控制台与伪终端

    (1)在本机上登录字符界面或者X11图形界面均为tty终端 (2)通过telnet/ssh远程登录或者在X11中生成一个XTERM的终端,均为虚拟终端PTS. 如: [lujinhong@localh ...

  5. linux 伪终端原理,探索Linux之 终端模拟器和伪终端交互原理

    写在前面:本人水平有限,不少地方都是本身的理解,若有误导,欢迎指正linux # 终端模拟器指的是在linux桌面环境下运行的仿真终端(以下图)shell # 终端模拟器为啥叫模拟器呢? 由于真正的终 ...

  6. 探索Linux之 终端模拟器和伪终端交互原理

    写在前面:本人水平有限,很多地方都是自己的理解,如有误导,欢迎指正 # 终端模拟器指的是在linux桌面环境下运行的仿真终端(如下图) # 终端模拟器为啥叫模拟器呢? 因为真正的终端是全屏显示的黑乎乎 ...

  7. SVR4/4.3BSD与Linux对待伪终端的不同方式

    打开伪终端意味着打开了一个"终端对",这个终端对的其中一个是主终端,另一个是从终端,简单说主终端和类似sshd,telnetd等用户空间的远程协议处理进程连接,而从终端则和shel ...

  8. android 伪终端,伪终端(pty)机制祥解

    -----------------------------------------------------------本文系本站原创,欢迎转载! 转载请注明出处:http://sjj0412.cubl ...

  9. 模拟linux终端测试java,Linux 伪终端(pty)

    通过<Linux 终端(TTY)>一文我们了解到:我们常说的终端分为终端 tty1-6 和伪终端.使用 tty1-6 的情况一般为 Linux 系统直接连了键盘和显示器,或者是使用了 vS ...

最新文章

  1. HTML POST提交参数给PHP并返回json,上传execl文件
  2. locate,find
  3. 微信小程序开发视频教程新鲜出炉
  4. 爬取小说2--协程间通信Python
  5. 关于核定区域电网2018—2019年输电价格的通知
  6. 【视频】React redux toolkit创建状态切片
  7. find_first_of()和 find_last_of() 【获取路径、文件名】
  8. 查找重复文件_重复文件查找和磁盘整理工具:Tidy Up
  9. Linux命令--- /dev/null和/dev/tty
  10. Python爬虫书籍分享
  11. 多尺度小波分解Matlab/Python实现与原理分析
  12. 【短视频运营】抖音推送机制 | 账号 “ 完播率 “ 数据
  13. 字节跳动java面试题,附详细答案解析
  14. TunePat Amazon Video Downloader使用教程
  15. 最新版苹果开发者账号注册续费流程 Apple Developer
  16. 答云淡风轻:汉化Rails报错信息,部署发布,NT服务
  17. 微信小程序如何保存图片到相册
  18. Python实现缺失数字的四种方法
  19. 简单几步解决ie打不开闪退的问题 亲测有效
  20. 敏捷与结构性模块化(二)

热门文章

  1. iOS身份证号码识别
  2. Android报错:java.lang.IllegalArgumentException: Surface was abandoned
  3. android 事件传递机制
  4. RxJava Rxandroid 结合 Retrofit 使用
  5. Android Launcher3(一) -- 启动过程
  6. 编程思想之多线程与多进程——以操作系统的角度述说线程与进程
  7. 第八周项目三-指向学生类的指针
  8. Kati详解-Android10.0编译系统(五)
  9. php操作MySQL
  10. 解锁UI自动化新姿势-UI Recorder