我有一个进程,它将一些压缩的输出转储到 stdout。我对此输出的处理方式是将其通过管道通过 SSH 隧道发送到另一台计算机,然后将其转储到文件中。
就像这样:
/usr/bin/myapp | ssh root@remotemachine "cat > /path/to/output/file.gz"
当我ssh
进入机器并调用此行时,一切都很顺利。但是当我把这个命令放在 shell 脚本中时,就像
#!/bin/sh
APP=/usr/bin/myapp
OPTS=--gzip
OUTPUT= "| ssh root@remotemachine \"cat > /path/to/output/file.gz\""
$APP $OPTS $OUTPUT
然后调用脚本,我在控制台上看到垃圾,我只能假设它是输出myapp
,然后是这个
Unknown parameter '|'
Unknown parameter 'ssh'
Unknown parameter 'root@remotemachine'
Unknown parameter '"cat'
Unknown parameter '>'
Unknown parameter '/path/to/output/file.gz"'
我猜想 shell 将该$OUTPUT
部分作为参数发送给它们,myapp
而不是对它们执行操作。因此,这些“未知参数”不是来自myapp
shell,而是来自其他部分。
我该如何修复这个问题?
答案1
您的 shell 会按照特定顺序解析任何命令行。当它遇到时,$APP $OPTS $OUTPUT
它会发现没有管道运算符;稍后这些变量会被展开并|
出现,但它没有特殊含义,因为此时已经太晚了。
eval
结果可以用(你的答案表明你已经发现了这一点)重新评估,但是eval
可能会拼写错误evil
。
你原来的方法是有缺陷的,因为 shell 变量不是为了包含代码。函数是用于代码的。例如:
app=/usr/bin/myapp
opts=--gzip
output() { ssh root@remotemachine "cat > /path/to/output/file.gz"; }
$app $opts | output
答案2
好的……我找到了我需要的东西。这是eval
命令。这实际上是答案这里。
因此,可以按如下方式修改脚本:
#!/bin/sh
APP=/usr/bin/myapp
OPTS=--gzip
OUTPUT= "| ssh root@remotemachine \"cat > /path/to/output/file.gz\""
eval "$APP $OPTS $OUTPUT"