我有两个正在尝试的远程服务器ssh
和cat
一些文件..我想将 ssh 的输出输入到awk
命令中。
这就是我所拥有的
ssh username@host1 “cat /tmp/test/*” ssh username@host2 “cat /tmp/test/*” | awk ‘ command ‘
但这不起作用,如果host2
目录为空,则输出host1
会重复两次。
我在这里做错了什么?
答案1
当心这些弯引号(“
和”
) 某些 Windows 文本编辑器会使用直引号 ('
或"
)。您还应该使用'
s,除非您有某种原因使用"
s,例如让变量扩展,请参阅https://mywiki.wooledge.org/Quotes。
如果你想要一个 awk 管道,你应该这样做:
{ ssh username@host1 'cat /tmp/test/*'; ssh username@host2 'cat /tmp/test/*'; } | awk ' command '
但请考虑这样做,以便 awk 可以区分输入来自哪个命令,以防将来需要这种区分:
awk ' command ' <(ssh username@host1 'cat /tmp/test/*') <(ssh username@host2 'cat /tmp/test/*')
区别如下:
$ seq 3 > file1
$ seq 2 > file2
错误的输出(因为FILENAME
总是包含-
且ARGV[1..2]
为空):
$ { cat file1; cat file2; } | awk '
FILENAME == ARGV[1] { host="host1" }
FILENAME == ARGV[2] { host="host2" }
{ print host, $0 }
'
1
2
3
1
2
错误的输出(因为FILENAME
和ARGV[1]
包含相同的临时文件描述符但ARGV[2]
为空):
$ awk '
FILENAME == ARGV[1] { host="host1" }
FILENAME == ARGV[2] { host="host2" }
{ print host, $0 }
' <(cat file1; cat file2)
host1 1
host1 2
host1 3
host1 1
host1 2
正确输出:
$ awk '
FILENAME == ARGV[1] { host="host1" }
FILENAME == ARGV[2] { host="host2" }
{ print host, $0 }
' <(cat file1) <(cat file2)
host1 1
host1 2
host1 3
host2 1
host2 2
通过这种提供输入的方法获得正确输出的其他可能方法:
$ awk '{print host, $0}' host='host1' <(cat file1) host='host2' <(cat file2)
host1 1
host1 2
host1 3
host2 1
host2 2
答案2
您需要对命令进行分组。最简单的方法是使用花括号将它们分组而不创建子 shell:
{ ssh username@host1 'cat /tmp/test/*'; ssh username@host2 'cat /tmp/test/*'; } |
awk ' command '
您还可以使用括号,但这有点不优雅,因为它创建了一个您不需要的子 shell。但是,最终结果是相同的,在这种情况下确实不应该产生任何影响。另外,您不需要像;
使用时那样添加结尾{ }
:
( ssh username@host1 'cat /tmp/test/*'; ssh username@host2 'cat /tmp/test/*' ) |
awk ' command '
您看到重复输出的原因是因为这两个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
正如您在上面看到的,这被解释为“ssh localhost cat arg1 arg2 arg3 arg4”,因此运行在(在您的情况下),并作为参数给出,,(cat
在localhost
您host1
的/tmp/test/*
情况ssh
下),然后再次。所以 host1 的内容被ted 两次。localhost
host2
cat
/tmp/test/*
/tmp/test
cat
答案3
一种可能的方法是在子 shell 中执行ssh
命令并将结果通过管道传输awk
:
(ssh username@host1 "cat /tmp/test/*"; ssh username@host2 "cat /tmp/test/*" ) | awk ‘ command ‘