两个 ssh 输出作为 awk 输入

Nec*_*der 4 shell bash ssh awk shell-script

我有两个正在尝试的远程服务器sshcat一些文件..我想将 ssh 的输出输入到awk命令中。

\n

这就是我所拥有的

\n
\nssh username@host1 \xe2\x80\x9ccat /tmp/test/*\xe2\x80\x9d ssh username@host2 \xe2\x80\x9ccat /tmp/test/*\xe2\x80\x9d | awk \xe2\x80\x98 command \xe2\x80\x98\n
Run Code Online (Sandbox Code Playgroud)\n

但这不起作用,如果host2目录为空,则输出host1会重复两次。

\n

我在这里做错了什么?

\n

Ed *_*ton 9

请注意某些 Windows 文本编辑器会使用的弯引号(\xe2\x80\x9c\xe2\x80\x9d),请改用直引号 (\'")。您还应该使用\'s,除非您有某种原因使用"s,例如让变量扩展,请参阅https://mywiki.wooledge.org/Quotes

\n

如果你想要一个 awk 管道,你应该这样做:

\n
{ ssh username@host1 \'cat /tmp/test/*\'; ssh username@host2 \'cat /tmp/test/*\'; } | awk \' command \'\n
Run Code Online (Sandbox Code Playgroud)\n

但请考虑这样做,以便 awk 可以区分输入来自哪个命令,以防将来需要这种区分:

\n
awk \' command \' <(ssh username@host1 \'cat /tmp/test/*\') <(ssh username@host2 \'cat /tmp/test/*\')\n
Run Code Online (Sandbox Code Playgroud)\n

区别如下:

\n
$ seq 3 > file1\n$ seq 2 > file2\n
Run Code Online (Sandbox Code Playgroud)\n

错误的输出(因为FILENAME总是包含-ARGV[1..2]为空):

\n
$ { cat file1; cat file2; } | awk \'\n    FILENAME == ARGV[1] { host="host1" }\n    FILENAME == ARGV[2] { host="host2" }\n    { print host, $0 }\n\'\n 1\n 2\n 3\n 1\n 2\n
Run Code Online (Sandbox Code Playgroud)\n

错误的输出(因为FILENAMEARGV[1]包含相同的临时文件描述符但ARGV[2]为空):

\n
$ awk \'\n    FILENAME == ARGV[1] { host="host1" }\n    FILENAME == ARGV[2] { host="host2" }\n    { print host, $0 }\n\' <(cat file1; cat file2)\nhost1 1\nhost1 2\nhost1 3\nhost1 1\nhost1 2\n
Run Code Online (Sandbox Code Playgroud)\n

正确输出:

\n
$ awk \'\n    FILENAME == ARGV[1] { host="host1" }\n    FILENAME == ARGV[2] { host="host2" }\n    { print host, $0 }\n\' <(cat file1) <(cat file2)\nhost1 1\nhost1 2\nhost1 3\nhost2 1\nhost2 2\n
Run Code Online (Sandbox Code Playgroud)\n

通过这种提供输入的方法获得正确输出的其他可能方法:

\n
$ awk \'{print host, $0}\' host=\'host1\' <(cat file1) host=\'host2\' <(cat file2)\nhost1 1\nhost1 2\nhost1 3\nhost2 1\nhost2 2\n
Run Code Online (Sandbox Code Playgroud)\n


ter*_*don 7

您需要对命令进行分组。最简单的方法是使用花括号将它们分组而不创建子 shell:

{ ssh username@host1 'cat /tmp/test/*'; ssh username@host2 'cat /tmp/test/*'; } | 
   awk ' command '
Run Code Online (Sandbox Code Playgroud)

您还可以使用括号,但这有点不优雅,因为它创建了一个您不需要的子 shell。但是,最终结果是相同的,在这种情况下确实不应该产生任何影响。另外,您不需要;像使用时那样添加结尾{ }

( ssh username@host1 'cat /tmp/test/*'; ssh username@host2 'cat /tmp/test/*' ) | 
   awk ' command '
Run Code Online (Sandbox Code Playgroud)

您看到重复输出的原因是因为这两个cat命令都在同一主机上运行。localhost检查用作两个命令的主机时以及运行后的输出set -x

$ ls /tmp/test
file1

$ ssh localhost "cat /tmp/test/*" ssh localhost "cat /tmp/test/*"
+ ssh localhost 'cat /tmp/test/*' ssh localhost 'cat /tmp/test/*'
/tmp/test/file1
/tmp/test/file1
cat: ssh: Is a directory
cat: localhost: No such file or directory
cat: cat: No such file or directory
Run Code Online (Sandbox Code Playgroud)

正如您在上面看到的,这被解释为“ssh localhost cat arg1 arg2 arg3 arg4”,因此cat运行在localhosthost1在您的情况下),并作为参数给出/tmp/test/*,,sshlocalhosthost2您的情况下),cat然后/tmp/test/*再次。所以 host1 的内容/tmp/testcatted 两次。