【问题标题】:Store output of grep command executed remotely using ssh to a variable?将使用 ssh 远程执行的 grep 命令的输出存储到变量中?
【发布时间】:2016-06-24 17:54:12
【问题描述】:

我正在尝试通过 jenkins 机器在远程服务器上运行一系列命令。 这些命令执行以下操作

  1. 在远程服务器上创建目录
  2. 将一些文件从远程服务器复制到该目录中

我已经创建了下面的脚本,

    servername=<remote server ip>

    sshuserconnect() {
        echo `/usr/bin/sshpass -p passwd ssh -o ConnectTimeout=5 -o UserKnownHostsFile=knownhosts -o StrictHostKeyChecking=no $*`
    }

sshuserconnect user@$servername << ENDOFSSH

    sqlplus -s /nolog << EOF > /home/user/output.txt
    connect user/pwd@$servername:<port>/<DB schema>
    select column1||','||value from table where column1 like 'param1';
    EOF

    version=`grep version /home/user/output.txt | cut -f 2 -d ","`
    mkdir /home/user/${version}

ENDOFSSH

脚本失败并出现以下错误,

grep: output.txt: No such file or directory
Pseudo-terminal will not be allocated because stdin is not a terminal.

经过一些调试,我发现脚本仅对 grep 命令失败。将 grep 输出分配给版本变量失败。

我尝试了很多选择,如果这是正确的方法,我不会。谁能帮我解决这个问题?

【问题讨论】:

  • 是的,这对我来说似乎是一个简单的错字。请注意,您可以使用 awk 代替 grep | cut: awk -F, '/version/ { print $2 }' output.txt
  • 两个建议,将 output.txt 更改为 ./output.txt,以防本地目录不是您的 PATH 的一部分。还将 ${Version} 更改为 ${version}。
  • @LAROmega,我已经编辑了问题并将文件路径更改为绝对路径。仍然错误保持不变。 @TomFenech,我尝试了你的方法,version='awk -F, '/version/ { print $2 }' /home/user/output.txt'。仍然错误是一样的。

标签: linux bash shell ssh grep


【解决方案1】:

在您的脚本中,`grep version ...` 的扩展是由本地 shell 而不是远程 shell 执行的。这同样适用于/home/user/${version} 的扩展。 my answerthe canonical question addressing problems of this kind 介绍了在此处文档中使用扩展的细节。

您的脚本属于混合大小写“3. 必须在子 shell 中执行某些扩展,在父 shell 中执行某些 - ”,并且必须按以下方式修复:

sshuserconnect user@$servername <<ENDOFSSH

sqlplus -s /nolog <<EOF > /home/user/output.txt
connect user/pwd@$servername:<port>/<DB schema>
select column1||','||value from table where column1 like 'param1';
EOF

version=\$(grep version /home/user/output.txt | cut -f 2 -d ",")
mkdir /home/user/\${version}

ENDOFSSH

请注意,我有意删除了&lt;&lt;ENDOFSSH here-document 中脚本部分的缩进,以便将EOF 正确识别为嵌套&lt;&lt;EOF here-document 的结束标记。有两种方法可以保留缩进:

  1. 缩进除EOF 结束标记之外的所有内容:

    sshuserconnect user@$servername <<ENDOFSSH
    
        sqlplus -s /nolog <<EOF > /home/user/output.txt
        connect user/pwd@$servername:<port>/<DB schema>
        select column1||','||value from table where column1 like 'param1';
    EOF
    
        version=\$(grep version /home/user/output.txt | cut -f 2 -d ",")
        mkdir /home/user/\${version}
    
    ENDOFSSH
    

    这看起来有点难看。

  2. 使用制表符而不是空格来缩进,并使用&lt;&lt;-ENDOFSSH 而不是&lt;&lt;ENDOFSSH,这会导致此处文档中的前导制表符被删除。在下面的代码中,我特意用&lt;TAB&gt; 标记了制表符,这既是为了明确,也是因为 StackOverflow 使用空格呈现制表符,这意味着复制和粘贴代码将无法正常工作:

    sshuserconnect user@$servername <<-ENDOFSSH
    
    <TAB>sqlplus -s /nolog <<EOF > /home/user/output.txt
    <TAB>connect user/pwd@$servername:<port>/<DB schema>
    <TAB>select column1||','||value from table where column1 like 'param1';
    <TAB>EOF
    
    <TAB>version=\$(grep version /home/user/output.txt | cut -f 2 -d ",")
    <TAB>mkdir /home/user/\${version}
    
    ENDOFSSH
    

【讨论】:

  • 很好的讨论,只有 nit 在 ' 阅读此内容'链接 this 应该是 完整标题(或至少是描述性的substring) 的文章你也指导用户。
  • @DavidC.Rankin 感谢您的建议。我更新了答案,但我找不到通过标题引用指向问题的好方法。
  • 看起来不错,只是为了确保用户的眼睛不会跳过您的链接。另一个技巧是加粗链接。
  • 感谢 Leon 的详细回答。它让我想到了重新编写我的工作并避免我正在做的错误。我现在可以正常运行我的脚本了。
猜你喜欢
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
相关资源
最近更新 更多