【问题标题】:Issue with passing find command via ssh通过 ssh 传递 find 命令的问题
【发布时间】:2021-07-02 19:09:43
【问题描述】:

我正在尝试读取特定文件的内容。我有多个这些文件所在的主机。我在 ssh 期间传递以下命令,以便它可以运行并获取输出。

  1. 当使用下面的命令时,我得到了指定的错误。 (它的 sshed 托管但没有任何反应)

    $ ssh host "more $(find /my/path -name "test*")"
    find: 0652-010 The starting directory is not valid.
    
  2. 当使用 exec 时它不起作用,(它的 sshed 到主机但没有任何反应)

    $ ssh host "find /my/path -name "test*" -exec more {} \;"`
    
  3. 当使用 xargs 时,它按预期工作

    $ ssh host "find /my/path -name "test*" | xargs more"
    

有人能解释一下为什么方法 1 和 2 不起作用吗?

请注意,如果我直接在远程主机上运行命令,则每种方法都可以正常工作。 例如,以下所有命令在远程主机中都按预期工作。

more $(find /my/path -name "test*")

find /my/path -name "test*" -exec more {} \;

find /my/path -name "test*" | xargs more

【问题讨论】:

    标签: linux bash unix ssh solaris


    【解决方案1】:

    对于 (1) “双引号字符串”中的 "... $(command substitution)" 正在由您的 local bash shell 完成,您需要对其进行转义,以便它可以看到并展开直到命令到达远程盒子:

    ssh host "more \$(find /my/path -name 'test*')"
    

    或者,因为“单引号”不会扩展 $()

    ssh host 'more $(find /my/path -name "test*")'
    

    注意 A - 上述解决方案还小心确保在到达远程框时仍然引用 test*(单引号或双引号),因为 @987654326 很重要@ 看到确切的字符串 test*,而不是它可能 glob/*/expand 到 IF 碰巧在远程主目录中有以 test 开头的文件名。

    对于 (2) 类似,您需要转义 \ 以便将其正确传递到远程框:

    ssh host "find /my/path -name 'test*' -exec more {} \\;"
    

    或者,因为“单引号”不能转义:

    ssh host 'find /my/path -name "test*" -exec more {} \;'
    

    对于 (3),请注意注意 A。当您的 (3) 命令到达远程主机时,test* 不会被引用。添加另一层或转义引号将使其更安全:

    ssh host "find /my/path -name \"test*\" | xargs more"
    

    ssh host "find /my/path -name 'test*' | xargs more"
    

    警告 B - 像 more 这样的程序会与您的终端/tty 交互,因此您可能需要强制远程 sshd 使用 ssh -t host ... 分配一个

    Caveat C - 以上所有内容都假设您的用户在远程机器上的 shell 是“普通”/Bourne 类型的 shell(bash、dash、ash、sh、zsh)。如果远程用户帐户已将其登录 shell 更改为奇怪的东西(tcsh、fish、...),您需要添加 another 层引号转义并在特定 shell 中调用您的命令(bash f /ex): ssh host "/bin/bash -c \"more \\\$(find /my/path -name 'test*')\""

    【讨论】:

      【解决方案2】:

      您的语法错误。特别看一下双引号:您将一组双引号括在test* inside 另一组双引号中。 shell应该怎么理解呢?相反,您必须“逃避”(保护)内部引号。你应该使用more(或less)命令locally,因为你想限制本地终端长度:

      您的第一次尝试的这个版本按预期工作:

      ssh host "find /my/path -name \"test*\"" | more
      

      【讨论】:

      • 我正在尝试查找文件并使用更多阅读。方法 3 也有内部引号,但是那个有效,那么为什么方法 1 不起作用?正如你提到的,我也尝试转义内部引号,但它不起作用。
      • 啊,这是不同的东西...您看到 find 返回文件列表,而不是文件内容...您可以使用 xargs 进一步处理(使用)这样的文件列表,但在 server 端没有more (less),因为那里没有终端。该命令无法决定屏幕的长度,因此在哪里停止输出。相反,它会刷新整个文件,就像 cat 会做的那样。这再次意味着您可以将该输出通过管道传输到 local 命令:ssh host "find /my/path -name \"test*\" | xargs cat" | more...
      【解决方案3】:

      答案是引用。

      在第一种情况下,您运行 find locally 。试试ssh host "echo $(hostname)"。第二种方法分别在合适的每个文件上运行more

      【讨论】:

        【解决方案4】:

        你应该这样做:

        ssh host "ksh -c 'find /my/path -name \"test*\" -exec more {} \;'"`

        当使用“-c”作为选项时,ksh 将命令读取为字符串并直接运行

        【讨论】:

          猜你喜欢
          • 2016-07-25
          • 1970-01-01
          • 1970-01-01
          • 2017-05-18
          • 1970-01-01
          • 2021-02-25
          • 2018-09-12
          • 1970-01-01
          • 2018-04-29
          相关资源
          最近更新 更多