在 wget 命令中使用 headers 的 user-provided 值的问题

Problems in using the user-provided values of headers in wget command

我正在编写一个简单的 bash shell 脚本;输出 url 的 page-load 时间。服务器仅在使用特定自定义 headers 请求时以正确的页面响应(仅供参考:缺少 headers 默认页面由服务器提供。) 要访问的 url 及其 headers 是从配置文件中读取的(由 semi-colon 分隔) 示例条目:http://google.com/;User-Agent:XYZ A;msisdn:98xxxxxxxx

我做了从读取文件到触发 wget 命令的所有事情。

但是,查看输出我发现,headers 字符串未正确传递(尽管我正在正确构建它)到 wget 命令。 在进一步调试时,我发现 bash/linux in-tern 将整个 headers 字符串包装到单引号中并将其发送到 wget 命令,因此 wget 无法给我预期的输出。

代码:

#!/bin/bash
load_page()
{
    echo "url=$url";
    echo "headers=$header_str";
    /usr/bin/time -f "\t%e\t%C" wget -kKHpq --no-cache "$header_str" "$url" 
}
read_config_file()
{
    while read cfg_line
    do
        if [[ ! "$cfg_line" = \#* ]] && [[ "x$cfg_line" != "x" ]] ; then    
            url=`echo $cfg_line | cut -d";" -f1`
            fields=`echo $cfg_line | awk -F";" ' { print NF } ' `; 
            f_cnt=2;
            unset header_str
            while [ $f_cnt -le $fields ] ; 
            do
                field=`echo $cfg_line | cut -d";" -f$f_cnt`;
                header_name=`echo $field | cut -d":" -f1`;
                header_val=`echo $field | cut -d":" -f2`;
                header_str="${header_str}--header=\"${header_name}: $header_val\" "
                f_cnt=`expr $f_cnt + 1`;
            done
            load_page 
        fi
    done<urls.cfg   
}
main()
{
    read_config_file
}
main $@

输出:

url=http://some-website.com/

headers=--header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx" 

6.37    wget -kKHpq --no-cache --header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx"  http://some-website.com/

一切看起来都很好,但是没有获取正确的页面。如果我从输出中复制粘贴命令,则服务器会响应预期的页面。

当 运行 shell 脚本处于调试模式时;我认为这是问题所在。 headers 字符串被包裹在 wget 命令中的单引号中。

请帮忙。

+ load_page
+ echo url=http://some-website.com/
url=http://some-website.com/
+ echo 'headers=--header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx" '
headers=--header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx" 
+ /usr/bin/time -f '\t%e\t%C' wget -kKHpq --no-cache '--header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx" ' http://some-website.com/
    1.66    wget -kKHpq --no-cache --header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx"  http://some-website.com/

嗯,您正在引用字符串,如果您删除引号会怎样?

/usr/bin/time -f "\t%e\t%C" wget -kKHpq --no-cache $header_str "$url"

引用的任何内容都应作为单个参数(字符串)传递。所以如果它没有被引用,它应该评估并将它们作为单独的参数传递

$header_str 被解释为单个参数,因为它用引号引起来。

尝试将您的 wget 命令更改为:

 /usr/bin/time -f "\t%e\t%C" wget -kKHpq --no-cache $header_str "$url" 

即使输出显示:

wget -kKHpq --no-cache --header="User-Agent: XYZ G" --header="msisdn: 98xxxxxxxx"  http://some-website.com/

传递给进程的 argv 数组的参数看起来像这样:

[ "wget", "-kKHpq", "--no-cache"  "-header=\"User-Agent: XYZ G\" --header=\"msisdn: 98xxxxxxxx\", "http://some-website.com/" ]

我建议使用 eval。为此,您需要将完整的命令构建为一个字符串,然后传递给 eval。我不适合用 wget 写出一个完整的例子,但基本的想法是:

my_args='-al'
eval "ls ${my_args}"

如果您从这个基本示例开始,我想您会发现您可以可靠地将命令的固定方面与配置中的用户字符串结合起来。

对于有关 evalexecsource 的使用的小而有用的讨论,我建议您阅读 bash shell: 'exec', 'eval', 'source' - looking for help to understand

上的这个帖子