终端将不会被分配,因为stdin不是终端
我正在尝试编写一个在远程服务器上创建一些目录的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
每当我运行它时,我都会收到以下消息:
Pseudo-terminal will not be allocated because stdin is not a terminal.
剧本永远挂起。
我的公钥在服务器上是可信的,我可以在脚本之外运行所有的命令。 有任何想法吗?
尝试使用ssh -t -t
(或简称ssh -tt
)来强制伪tty分配,即使stdin不是终端。
另请参见:终止由bash脚本执行的SSH会话
从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.
还有手动选项-T
禁用伪tty分配
Per zanco的回答是,你没有提供远程命令给ssh
,因为shell解析命令行的方式。 要解决此问题,请更改ssh
命令调用的语法,以便远程命令由语法正确的多行字符串组成。
有多种可以使用的语法。 例如,由于可以将命令传送到bash
和sh
,也可能是其他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
请注意,执行上面没有/bin/bash
将导致警告Pseudo-terminal will not be allocated because stdin is not a terminal
。 还要注意, EOT
被单引号括起来,所以bash
将heredoc识别为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
警告适用于上述情况。
另一种有效的方法是将多行远程命令作为单个字符串传递,使用多层bash
变量插值,如下所示:
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
上述解决方案以下列方式解决了此问题:
ssh user@server
被bash解析,并被解释为ssh
命令,随后是一个参数user@server
以传递给ssh
命令
"
开始一个插入的字符串,当完成时,它将包含一个参数传递给ssh
命令,在这种情况下,它将被ssh
解释为要作为user@server
执行的远程命令
$(
开始一个要执行的命令,输出被周围的内插字符串捕获
cat
是一个输出任何文件内容的命令。 cat
的输出将被传回到捕获的内插字符串中
<<
开始一场狂欢heredoc
'EOT'
指定heredoc的名称是EOT。 单引号'
周围的EOT指定的定界符应被解析为一个nowdoc,这是定界符的一种特殊形式,其内容不要被bash的插值,但在文字格式,而传递
在<<'EOT'
和<newline>EOT<newline>
之间遇到的任何内容将被附加到nowdoc输出
EOT
终止nowdoc,导致创建一个nowdoc临时文件并将其传递回调用cat
命令。 cat
输出nowdoc并将输出传递回捕获内插字符串
)
结束要执行的命令
"
结束捕获内插字符串,内插字符串的内容将作为单个命令行参数传递回ssh
,该ssh
将解释为要作为user@server
执行的远程命令
如果您需要避免使用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 )"
EOT
ssh user@server "${SSH_COMMAND}"
链接地址: http://www.djcxy.com/p/17501.html
上一篇: terminal will not be allocated because stdin is not a terminal