设想:
我有一个脚本用于连接到远程主机并从日志文件中 grep 特定关键字。如果不使用 EOF,ssh 就会被冻结,但是当使用 heredoc (EOF) 时,这个问题就消失了。我的所有命令都必须在 ssh 到远程主机后执行,因此它们位于 EOF 块内。
grep 命令给我的输出为:“没有这样的文件或目录”,而我在终端上执行了相同的命令,它给出了所需的输出。
下面是有问题的 grep 代码:
ssh -q -T username@remotehost <<-EOF 2>&1 | tee -a
getValue=$(grep -R 'keyword' /user/log/file.log | awk -F ' ' '{print$NF}') )
echo "${getValue}"
EOF
Output: grep: /user/log/file.log : No such file or directory
当我打印远程主机并进一步交叉检查日志路径和 file.log 时,SSH 工作正常。从设置的角度来看,一切都已就位。通过互联网进行了一些研发,但到目前为止没有任何帮助。
答案1
您需要引用您'EOF'
以防止您的外壳程序$
在本地解释,即。尝试在远程命令之前在 shell 中运行 grep 。
比较:
ssh username@remotehost << 'EOF'
echo "THIS IS $(hostname)"
EOF
和
ssh username@remotehost << EOF
echo "THIS IS $(hostname)"
EOF
答案2
您的问题来自于让 shell 在本地而不是远程系统上扩展此处文档中的命令替换。这样做是因为此处的文档没有被引用。出于同样的原因,它还会将$NF
和作为 shell 变量扩展为空字符串(除非这些 shell 变量之前有值)。 ${getValue}
shell 不会注意到程序$NF
中使用了awk
。
不必尝试通过在远程主机上运行复杂的命令ssh
,只需使用ssh
来获取数据,然后在该数据上本地运行命令:
ssh username@remotehost cat /user/log/file.log |
awk -F ' ' '/keyword/ { print $NF }'
我也稍微简化了您的管道,将递归 (?!)grep
与结合awk
起来,以便awk
命令打印包含 substring 的行上的最后一个空格分隔的字段keyword
。
另请注意,如果您只想输出该变量的内容(echo
在某些情况下可能会另外修改在打印之前给出的数据),则将输出分配给变量是没有意义的。我还删除了tee -a
似乎没有多大作用的电话。
答案3
大约一周前,我使用包装脚本概念实现了所需的目标。只是为任何可能遇到同样问题的新用户发布此链接。
当然,这不是一个新概念,和许多其他概念一样,我在在这里发布我的问题之前也知道它。我真的想通过一个脚本来实现这一点,但不知何故,ssh 到远程主机后的变量扩展不能处理同一脚本中的所有内容。所以花那么多精力是不值得的。
创建一个包装脚本并在其中调用主脚本。在包装器中执行 ssh 命令,并将主脚本作为参数传递。就像是:
ssh username@host < main_script.sh
如果您有多个主机,请在读取变量“host”中的主机服务器值后将 ssh 置于 for/while 循环中。
while read -r host
do
servers=${host}
ssh username@${host} < main_script.sh
done < ${servers}
感谢大家提出建议!!