我正在尝试使用
wget
下载 bash 脚本并将其通过管道传输到 sh
,但我遇到了问题。它在单独的步骤中工作正常(wget 下载,然后执行),但在管道到 sh 时则不然。该脚本可以在 this gist 中找到,但为了方便起见,我会将其包含在这个问题的底部。
我正在运行以下命令:
linux
wget -q --no-cache https://gist.githubusercontent.com/devklick/be9cbe0b384958a7e7ce115f7df25e5a/raw/27153ef3109e7561e45f0fe43e9a10276da78252/install.sh -O - | sh -s linux
当我运行上面的代码时,脚本尝试解析从 Githubs REST API 返回的一些 JSON 失败。我们可以看到记录的最后几行如下所示:
GDMan/zipball/v1.3.1", "body": "## [1.3.1](https://github.com/devklick/GDMan/compare/v1.3.0...v1.3.1) (2024-05-07)
### Bug Fixes
* fixes [#15](https://github.com/devklick/GDMan/issues/15), --help is not a known command ([ddd78f2](https://github.com/devklick/GDMan/commit/ddd78f2a92da239bab9a08658b732d1460b19dc3))
" }
parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 150, column 1
Found download ''
我猜这里显示的换行符就是问题所在。不过使用wget下载保存文件然后执行就不存在这个问题了:
wget -q --no-cache https://gist.githubusercontent.com/devklick/be9cbe0b384958a7e7ce115f7df25e5a/raw/27153ef3109e7561e45f0fe43e9a10276da78252/install.sh
chmod +x ./install.sh
./install.sh linux
单独运行这些步骤,我们可以看到最后几行输出看起来有点不同:
GDMan/zipball/v1.3.1", "body": "## [1.3.1](https://github.com/devklick/GDMan/compare/v1.3.0...v1.3.1) (2024-05-07)\n\n\n### Bug Fixes\n\n* fixes [#15](https://github.com/devklick/GDMan/issues/15), --help is not a known command ([ddd78f2](https://github.com/devklick/GDMan/commit/ddd78f2a92da239bab9a08658b732d1460b19dc3))\n\n\n\n" }
Found download 'https://github.com/devklick/GDMan/releases/download/v1.3.1/GDMan_v1.3.1_linux-x64.zip'
所以问题是;为什么我的脚本在写入文件系统时与写入内存时表现不同,如何修复此问题以解决 JSON 换行问题,而无需在运行脚本之前先保存脚本?
我知道我可以通过单独运行这些步骤但用
&&
链接它们来解决这个问题,但我现在已经投入到这个问题中,并且真的很想知道问题/解决方案是什么。
有问题的 Bash 脚本:
#!/bin/bash
target_os=$1
echo "Target OS '$target_os'"
zip_path="$HOME/Downloads/gdman.zip"
echo "Asset download path '$zip_path'"
install_dir="$HOME/gdman"
echo "App install path '$zip_path'"
# Download the latest release information from GitHub API
echo "Finding latest version"
response=$(curl -s https://api.github.com/repos/devklick/GDMan/releases/latest)
echo $response
# Extract the browser download URL for the asset
download_url=$(echo "$response" | jq -r '.assets[] | select(.name | test("'${target_os}'")) | .browser_download_url')
echo "Found download '$download_url'";
发生这种情况是因为您在一种情况下使用
sh
(可能是 dash
),而在另一种情况下使用 bash
,并且 echo
不可在 shell 之间移植。
您的文件在 JSON 字符串中包含
\n\n
,每个字符串给出不同的结果:
$ bash -c 'echo "\n\n"'
\n\n
$ dash -c 'echo "\n\n"'
(blank line)
(blank line)
这是POSIX:
除非省略 -n(作为第一个参数)和转义序列,否则不可能在所有 POSIX 系统中可移植地使用 echo。
如果您希望脚本跨多个 shell 运行,可以将
echo
替换为 printf
,或者直接从 curl
到 jq
进行管道传输。