经过研究,我不确定这在 bash 脚本中是否可行。我发现最可能的原因是 bash 的 shell 扩展顺序。 (或许?)
我希望发生什么,
能够>
通过先前的变量启用/禁用语句的重定向 ( )。
例如:下面的 printf 输出应该>
根据变量$SendGrafana
包含的内容进行(重定向)。
但是这个示例代码不起作用:
SendGrafana=" > /dev/tcp/192.168.1.242/5062"
awk -v vars="$vars" 'BEGIN{printf "output.api %s \n", vars;}' $SendGrafana
我希望上面的代码能像这样工作:
awk -v vars="$vars" 'BEGIN{printf "output.api %s \n", vars;}' > /dev/tcp/192.168.1.242/5062
另外-当我使用 set -x (用于调试)运行脚本时,我看到单引号 (') 仅围绕重定向 (>) ,我认为这是问题所在,因为没有任何内容发送到我的 netcat 侦听器。我读到这只是为了用户使用 set -x 时的可读性,但是问题仍然存在。
以下是启用 set -x 时的相关输出:
+ awk -v vars=3 'BEGIN{printf "output.api %s \n", vars;}' '>' /dev/tcp/192.168.1.242/5062
(注意“>”)
我尝试了很多方法,无论是在变量声明还是变量扩展,但在调用脚本时都无法将输出重定向到 192.168.1.242:5062。谢谢
编辑如下- (在我的评论中添加这部分,因为我试图使问题简短,但建议应该在这里):
添加更多上下文:我什至使用这个$SendGrafana
变量的原因,而不是没有变量并且> /dev/tcp/192.168.1.242/5062
在每个 awk 语句之后逐字逐句 - 是这样我可以轻松设置$SendGrafana= " "
,并且我的脚本将输出到 STDOUT (而不是通过 发送到 192.168.1.242 > /dev/tcp/192.168.1.242/5062
) 。我仅在调试/测试添加新语句期间需要 STDOUT 上的输出。
答案1
问题确实是评估顺序。
这只是将文本放入命令行:shell 来实现重定向已经太晚了。
paul $ j=" > foo.txt "
paul $ echo Words Here $j
Words Here > foo.txt
paul $ ls -l foo.txt
ls: cannot access 'foo.txt': No such file or directory
这会导致 shell 重新评估整个命令。
paul $ eval echo Words Here $j
paul $ ls -l foo.txt
-rw-r--r-- 1 paul paul 11 Aug 19 22:38 foo.txt
paul $ cat foo.txt
Words Here
paul $
内置的 eval 可能很难正确使用,因此我尽可能避免使用它。您的命令会被评估两次(一次作为 eval 的参数,另一次由 eval 本身),这可能会使您的引用变得困难和乏味(特别是在涉及 awk 的情况下,已经需要单引号和双引号。)此外,错误可能会导致您的作为命令执行的变量,会产生意想不到的后果。更多这里:
unix.stackexchange.com/questions/278427/why-and-when-should-eval-use-be-avoided-in-shell-scripts
添加的示例:
我发布的 StackExchange 链接中的一个建议是让 shell 创建一个新的文件描述符,然后首先将其定向到目标。
这是一个有点夸张的测试脚本。
#! /bin/bash
#.. First arg to script is -l for test runs.
#.. For your live action.
Grafana="/dev/tcp/192.168.1.242/5062"
#.. For my demo here.
Grafana="./foo.txt"
rm -f foo.txt
if [[ "${1}" = "-l" ]]; then
exec 7>&1
shift 1
else
exec 7>"${Grafana}"
fi
vars="${@}" #.. Rest of args to output.
awk -v vars="$vars" 'BEGIN{printf "output.api %s \n", vars;}' 1>&7
ls -l foo.txt && cat foo.txt
并进行测试,记录到终端,然后记录到命名文件/设备。
Paul--) ./Swit -l Easy Living
output.api Easy Living
ls: cannot access 'foo.txt': No such file or directory
Paul--) ./Swit Easy Living
-rw-r--r-- 1 paul paul 24 Aug 20 09:22 foo.txt
output.api Easy Living
Paul--)
您可以将 fd 7 保持打开状态,并在脚本中多次使用它。你可以用以下命令关闭它exec 7>&-