当通过 shell 脚本中的变量传递参数时,curl 不起作用

当通过 shell 脚本中的变量传递参数时,curl 不起作用

直接在控制台输入以下命令即可运行:

[root@server user]# curl -d 'parameter=170.22.16.14 192.10.2.24 - - [01/Jan/1900:00:00:00 -0300] "GET  /files/notes.txt HTTP/1.1" 200 112061 "-" "Java/1.8.0.160"' -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add

另一方面,我有一个 bash 脚本addinfo.sh

#!/bin/bash

tail -n0 -F info.txt | while read LINE; do
    ins="curl -d 'parameter=$LINE' -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add"
    echo $ins
    $ins
done

然后我执行以下 echo 指令,输出显示为 keep:

[root@server user]# echo '170.22.16.14 192.10.2.24 - - [01/Jan/1900:00:00:00 -0300] "GET  /files/notes.txt HTTP/1.1" 200 112061 "-" "Java/1.8.0.160"' >> info.txt
[root@server user]# curl -d 'parameter=170.22.16.14 192.10.2.24 - - [01/Jan/1900:00:00:00 -0300] "GET  /files/notes.txt HTTP/1.1" 200 112061 "-" "Java/1.8.0.160"' -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add
curl: option -: is unknown
curl: try 'curl --help' or 'curl --manual' for more information

HTTP 请求未执行。以下输入数据无法更改:

170.22.16.14 192.10.2.24 - - [01/Jan/1900:00:00:00 -0300] "GET  /files/notes.txt HTTP/1.1" 200 112061 "-" "Java/1.8.0.160"

那么我该怎么做才能更正 Bash 脚本呢?

答案1

ins="curl -d 'parameter=$LINE' -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add"

您放入变量中的是 shell 语法,它是您在 shell 命令行(以交互方式或在脚本中)上输入的形式的命令,以便 shell 进行解析。

$ins

但这不会解析 shell 语法的变量内容。相反,它只是对值应用分词和通配符,并使用结果字段作为命令名称和参数。这与处理引号、运算符(包括重定向)或扩展(带有美元符号或反引号)等语法元素不同。

此处生成命令名称和参数curl、、、、、等。-d 'parameter=170.22.16.14192.10.2.24--

请注意那里的硬引号。这与运行 shell 命令时得到的结果相同

curl -d "'parameter=170.22.16.14" 192.10.2.24 - - etc.

原则上的根本区别在于变量应该包含数据,并且数据不会被解析为代码。您可能希望它在使用引号时也能这样工作,但这也意味着例如任何命令替换都会运行并且看起来像它们的字符串可以出现在例如命令行参数或文件名中。以任何合理的方式处理任意字符串都是不可能的。

为了正确起见,不要将代码放入数据中,只需直接运行命令:

tail -n0 -F info.txt | while read LINE; do
    curl -d "parameter=$LINE" -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add
done

或者,如果您愿意,请先将命令存储在函数中:

f() {
    curl -d "parameter=$1" -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add
}
tail -n0 -F info.txt | while read LINE; do
    f "$LINE"
done

如果您想在运行时打印该命令,您可以使用set -xshell 打印它实际​​运行的内容。 (Bash 会以适合再次作为 shell 输入的明确格式执行此操作,其他格式可能会产生不明确的输出。)

修改上面的函数:

f() (
    set -x
    curl -d "parameter=$1" -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add
)

或者您可以将整个命令存储在一个数组中,打印它然后运行它。 (不过,这给出了不明确的输出):

f() {
    cmd=(curl -d "parameter=$1" -H 'Content-Type: application/x-www-form-urlencoded' -X POST http://192.138.1.10:8080/system/add)
    printf "%s " "${cmd[@]}"
    echo
    "${cmd[@]}"
}

看:我们如何运行存储在变量中的命令?

相关内容