Yocto中带SAS_TOKEN的SOURCE_MIRROR_URL遇编码失败的解决方案咨询
我之前刚好碰到过一模一样的问题!BitBake的fetch模块默认会对整个URL进行URL编码,把SAS Token里的?、&这些特殊字符转成%3F、%26,这就导致Azure Blob服务没法正确解析你的SAS参数了。不用修改Poky核心源码的话,有几个实用的解决方案:
方案1:自定义wget fetch命令,绕过默认编码
BitBake默认用wget获取资源时,会自动编码URL。我们可以直接自定义BB_FETCH_CMD_wget变量,让它直接使用拼接好的完整URL(包含未编码的SAS Token),不让BitBake插手编码过程:
# 在local.conf或自定义bbclass中添加 SAS_TOKEN = "?sv=2019-12-12&ss=bf&srt=co&sp=rdl&se=2020-08-19T17:38:27Z&st=2020-08-19T09:38:27Z&spr=https&sig=abcdef_TEST" INHERIT += "own-mirrors" SOURCE_MIRROR_URL = "https://somewhere.blob.core.windows.net/our-mirror/downloads/BASENAME${SAS_TOKEN}" BB_FETCH_PREMIRRORONLY = "1" # 关键:自定义wget命令,直接传递完整URL BB_FETCH_CMD_wget = "wget -t 2 -T 30 --passive-ftp -P ${DL_DIR} '${SOURCE_MIRROR_URL/${BASENAME}/${URI}}'"
这里的${SOURCE_MIRROR_URL/${BASENAME}/${URI}}会把SOURCE_MIRROR_URL里的BASENAME替换成实际要下载的文件名,然后用单引号包裹整个URL,避免shell解析特殊字符,同时跳过BitBake的默认编码逻辑。
方案2:改用PREMIRRORS变量配置镜像
SOURCE_MIRROR_URL的处理逻辑会触发URL编码,而PREMIRRORS的替换规则不会自动编码URL。你可以把镜像配置改成PREMIRRORS的形式:
SAS_TOKEN = "?sv=2019-12-12&ss=bf&srt=co&sp=rdl&se=2020-08-19T17:38:27Z&st=2020-08-19T09:38:27Z&spr=https&sig=abcdef_TEST" INHERIT += "own-mirrors" BB_FETCH_PREMIRRORONLY = "1" # 为所有协议添加预镜像规则 PREMIRRORS_prepend = " \ git://.* https://somewhere.blob.core.windows.net/our-mirror/downloads/${BASENAME}${SAS_TOKEN};protocol=https \ http://.* https://somewhere.blob.core.windows.net/our-mirror/downloads/${BASENAME}${SAS_TOKEN};protocol=https \ https://.* https://somewhere.blob.core.windows.net/our-mirror/downloads/${BASENAME}${SAS_TOKEN};protocol=https \ "
PREMIRRORS的格式是<原协议匹配规则> <镜像URL>,这里用${BASENAME}自动替换成目标文件名,SAS Token直接拼接在后面,BitBake会直接使用这个未编码的URL去请求资源。
方案3:自定义fetch类重写encodeurl函数
如果上面的方案不适用,还可以通过自定义bbclass来替换BitBake的encodeurl函数,只对URL的基础部分编码,保留SAS Token的原始格式:
- 创建一个自定义bbclass文件(比如
azure_sas_mirror.bbclass):
python __anonymous() { from bb.fetch2 import encodeurl as original_encodeurl def custom_encodeurl(url): sas_token = d.getVar("SAS_TOKEN", True) if sas_token and sas_token in url: # 拆分URL的基础部分和SAS Token base_url, _ = url.split(sas_token, 1) # 只编码基础URL,SAS Token直接拼接 encoded_base = original_encodeurl(base_url) return encoded_base + sas_token return original_encodeurl(url) # 替换全局的encodeurl函数 import bb.fetch2 bb.fetch2.encodeurl = custom_encodeurl }
- 在
local.conf中继承这个类:
INHERIT += "azure_sas_mirror" SAS_TOKEN = "?sv=2019-12-12&ss=bf&srt=co&sp=rdl&se=2020-08-19T17:38:27Z&st=2020-08-19T09:38:27Z&spr=https&sig=abcdef_TEST" INHERIT += "own-mirrors" SOURCE_MIRROR_URL = "https://somewhere.blob.core.windows.net/our-mirror/downloads/BASENAME${SAS_TOKEN}" BB_FETCH_PREMIRRORONLY = "1"
这个方案通过动态替换BitBake的编码函数,实现了对SAS Token的特殊处理,完全不需要修改Poky的核心代码。
内容的提问来源于stack exchange,提问作者Jahn

