Unix/Linux 通过 ssh 运行复杂的命令

Orm*_*msk 2 grep ssh find

我正在尝试通过 ssh 连接到服务器,然后在这些文件中找到今天的文件然后 grep。但我收到一个错误,find: missing argument to `-exec'.

我在这里缺少什么?

ssh server.name find /dir1/subdir/filelist* -maxdepth 1 type f -mtime 0 -exec grep 'pattern' {} \;
Run Code Online (Sandbox Code Playgroud)

Kam*_*ski 8

您的代码存在的问题:

  1. 本地外壳可以扩展/dir1/subdir/filelist*到一个或多个匹配路径。这些路径可能存在也可能不存在于远程端。

  2. 本地ssh从它获得的多个参数构建 shell 代码(在远程端运行)。论据是:

    • find
    • /dir1/subdir/filelist* (如果没有本地匹配)
    • -maxdepth
    • 1
    • -type(我假设你type是一个错字)
    • f
    • -mtime
    • 0
    • -exec
    • grep
    • pattern (因为本地shell用完了引号)
    • {}
    • ; (因为本地 shell 用完了反斜杠)

    构建的shell命令是:

    find /dir1/subdir/filelist* -maxdepth 1 -type f -mtime 0 -exec grep pattern {} ;
    
    Run Code Online (Sandbox Code Playgroud)

    这不是一个有效的find命令,因为(远程)shell 将解释;为命令终止符,因此;永远不会到达find. 另请注意pattern,在远程 shell 的上下文中未加引号。

我认为这是您要在远程端的 shell 中运行的确切命令:

find /dir1/subdir/filelist* -maxdepth 1 -type f -mtime 0 -exec grep 'pattern' {} \;
Run Code Online (Sandbox Code Playgroud)

请参阅如何通过 ssh 执行复杂的命令行以及我在那里的回答。我不会在这里重复所有内容。最重要的事情:

为了控制远程 shell 将得到什么$command_line_built_by_ssh,您需要理解、预测和策划之前发生的解析和解释。你需要制作你的本地命令,所以本地 shell 并ssh消化它之后,它就会成为$command_line…你想要在远程端执行的确切命令。

一个基本的解决方案是将精确的(远程)命令ssh作为单个参数传递给本地。在您的情况下,本地命令可能是:

ssh server.name 'find /dir1/subdir/filelist* -maxdepth 1 -type f -mtime 0 -exec grep '\''pattern'\'' {} \;'
Run Code Online (Sandbox Code Playgroud)

在我对链接问题的回答中,我讨论了更多的想法。


Ral*_*edl 6

您没有使用此 ssh 命令运行多个命令,只是一个更复杂的 find 命令。

这里有两个主要问题。

  • 您编写命令的方式,将在客户端评估 glob 模式。
  • 错误消息的原因是;没有到达find命令。基本上,ssh连接参数并将它们传递到sh -c服务器上。你需要类似的东西\\\;

除非您需要服务器上的 stdin,否则最简单的解决方案是将 stdin 上的命令发送到 shell。这消除了对引号的需要。

ssh server.name /bin/sh <<'EOF'
find /dir1/subdir/filelist* -maxdepth 1 -type f -mtime 0 -exec grep 'pattern' {} \;
EOF
Run Code Online (Sandbox Code Playgroud)

  • 你可以跳过`cat`而只写`ssh sever.name /bin/sh &lt;&lt;EOF`。你也错过了 `type` 错误类型。 (3认同)