我正在尝试编写一个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通常会出现问题。使用command-to-run-as- 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'

(所有这些都包含在一个以'分隔的多行命令行参数中)。

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

你想用-t实现什么呢?

其他回答

还有manual中的选项-T

禁用伪tty分配

我不知道挂起的原因是什么,但是将命令重定向(或管道)到交互式ssh通常会出现问题。使用command-to-run-as- 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'

(所有这些都包含在一个以'分隔的多行命令行参数中)。

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

你想用-t实现什么呢?

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

解决方案

M-x自定义变量(然后按Enter) tramp-default-method(然后再次按Enter键) 在文本框中输入plink,然后应用并保存缓冲区 每当我尝试访问远程服务器时,我现在使用C-x-f /user@host:,然后输入密码。现在在Windows上的Emacs下正确地建立了到远程服务器的连接。

在看了很多这样的答案之后,我想分享一下我的解决方案。我只是在heredoc之前添加了/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

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

请参见:终止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.