【问题标题】:SSH while-loop in bash. Pseudo-terminal will not be allocated because stdin is not a terminalbash 中的 SSH while 循环。不会分配伪终端,因为 stdin 不是终端
【发布时间】:2019-08-13 10:48:52
【问题描述】:

我正在尝试将文件循环到 ssh 到服务器列表,并在这些服务器上为某些日志文件执行查找命令。我知道 ssh 会吞下整个输入文件。所以我使用 -n 参数来 ssh。这工作正常,但在某些服务器上我遇到了一个新错误。

输入文件的构建方式如下: 服务器名称:位置:时间:日志文件扩展

我使用的 Bash 中的代码是:

sshCmd="ssh -n -o ConnectTimeout=5 -o Batchmode=yes -o StrictHostKeyChecking=no -o CheckHostIP=no -o PasswordAuthentication=no -q"

while IFS=: read -r f1 f2 f3 f4 ; do        
$sshCmd "$f1"
find "$f2" -type f -name "$f4" -mtime +"$f3"

在某些服务器上我收到以下错误:

不会分配伪终端,因为 stdin 不是终端。 stty:标准输入:设备的 ioctl 不合适

我尝试了多种选择来解决这个问题。我已经使用了 -t、-tt、-T 选项,但是当使用这些选项时,相同的错误仍然存​​在,或者终端变得无响应。

谁有解决办法?

【问题讨论】:

  • 考虑使用 Ansible 或 Puppet Bolt 完成此类任务。
  • @brunorey 那不是 atm 选项
  • sshCmd 应该是一个函数,而不是一个变量。
  • find 命令是否应该在远程主机上运行?如图所示,您正在尝试启动交互式 shell(默认命令)。
  • 我从未说过它会解决问题;无论如何,它应该是一个函数。见Bash FAQ 050。而且由于find 必须在远程机器上运行,您需要将其指定为to ssh 的实际参数,而不是在下一行写成单独的命令。

标签: bash while-loop pty stty


【解决方案1】:

你没有在远程主机上运行find;您正在尝试在远程主机上运行登录 shell,只有在退出之后才会运行 find。此外,由于-n 选项,它的标准输入从/dev/null 重定向,远程shell 失败。

sshCmd="ssh -n -o ConnectTimeout=5 -o Batchmode=yes -o StrictHostKeyChecking=no -o CheckHostIP=no -o PasswordAuthentication=no -q"

while IFS=: read -r f1 f2 f3 f4 ; do   
  # Beware of values for f2, f3, and f4 containing double quotes themselves.     
  $sshCmd "$f1" "find \"$f2\" -type f -name \"$f4\" -mtime +\"$f3\""
done

不相关,但sshCmd 应该是一个函数,而不是要扩展的变量。

sshCmd () {
  ssh -n -o ConnectTimeout=5 -o Batchmode=yes -o StrictHostKeyChecking=no -o CheckHostIP=no -q "$@"
}

while IFS=: read -r f1 f2 f3 f4; do
   sshCmd "$f1" "find \"$f2\" -type f -name \"$f4\" -mtime +\"$f3\""
done

【讨论】:

  • 这项工作有 1 个例外。当我 ssh 到 SunOS 机器时,我仍然收到以下错误:将不会分配伪终端,因为 stdin 不是终端。 Oracle Corporation SunOS 5.10 Generic Patch 2005 年 1 月 当我离开 -n 选项时,我可以 ssh,但它会破坏 while 循环的功能。有什么建议吗? @chepner
  • 如果你使用-T显式禁用伪终端分配会发生什么?
  • 似乎输入文件对于该特定服务器不正确。所以原来的解决方案仍然适用并且有效。我的错。
【解决方案2】:

小补充:为自己省点反斜线的痛苦:

while IFS=: read -r f1 f2 f3 f4; do
   sshCmd "$f1" "find '$f2' -type f -name '$f4' -mtime +'$f3'"
done

双引号内的所有内容都将在命令处理之前被扩展,因此值将被扩展,并位于单引号内,以供远程主机处理;即远程主机将看到值,而不是变量名。

(标准免责声明适用于 f1、f2、f3、f4 包含单引号的可能性...)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-30
    • 2018-07-16
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 2017-10-31
    相关资源
    最近更新 更多