我正在尝试远程运行脚本并使用其标准输出来填充变量。我这样做是为了避免临时文件。
这是我正在尝试的模式:
var=$(bash <(curl -fsSkL http://remote/file.sh))
echo "var=${var}"
我正在测试这个模式而不curl
使用cat
:
var=$(bash <(cat ./local/file.sh))
echo "var=${var}"
这应该就语法而言是相同的。 ./local/file.sh
contains echo hello
,所以我希望var
包含 value hello
,但可惜的是,执行上述结果如下:
test.sh: command substitution: line 4: syntax error near unexpected token `('
test.sh: command substitution: line 4: `bash <(cat ./local/file.sh)'
var=
如何在不使用临时文件的情况下实现我的目标?
答案1
bash
这些是当 shell 在 POSIX 模式下运行时尝试执行进程替换时出现的错误。 shellbash
不支持 POSIX 模式下的进程替换。
bash
将以 POSIX 模式运行,当
set -o posix
已被使用,或- shell 被调用为
sh
.
我的预感是你有一个脚本,test.sh
你正在运行它sh test.sh
或者有一个#!/bin/sh
hashbang 行,并且你sh
恰好是bash
。另一种可能性是脚本确实不是#!
根本有-line,并且它被bash
-as-sh
以某种其他方式调用。
相反,请确保您的test.sh
脚本被 调用bash
。
例子:
$ cat script.sh
echo hello
$ cat test.sh
var=$(bash <( cat script.sh ))
printf 'var="%s"\n' "$var"
$ bash -o posix test.sh
test.sh: command substitution: line 2: syntax error near unexpected token `('
test.sh: command substitution: line 2: `bash <( cat script.sh ))'
var=""
$ bash test.sh
var="hello"
test.sh
如果您想使用 POSIX在脚本中以可移植的方式执行此操作sh
:
var=$( cat script.sh | bash )
printf 'var="%s"\n' "$var"
这将影响进程bash
读取其标准输入的输出cat
,即不完全的与您的流程替换变体相同(仅保留标准输入)。如果内部 shell 执行的脚本以bash
任何形式从其标准输入读取数据,这一点很重要。
如果您需要bash
单独保留 shell 的标准输入(因为您需要从中读取),您可能会假设它mktemp
可用并使用
var=$( tmpfile=$(mktemp); cat script.sh >"$tmpfile" && bash "$tmpfile"; rm -f "$tmpfile" )
printf 'var="%s"\n' "$var"
其中cat script.sh
理解为稍后替换为您的curl
命令。
如果您习惯于处理文件描述符,您还可以在调用 shell 之前将文件描述符 3 制作为标准输入描述符的副本bash
,然后让获取的脚本从中读取:
var=$( exec 3<&0; cat script.sh | bash )
printf 'var="%s"\n' "$var"
然后该script.sh
脚本将用于read -u 3
读取原来的标准输入流,或utility <&3
将该输入流重定向到另一个实用程序。