读取输入,同时通过标准输入管道传输脚本



我有一个简单的 Bash 脚本:

#!/usr/bin/env bash
read X
echo "X=$X"

当我用./myscript.sh执行它时,它可以工作。但是当我用cat myscript.sh | bash执行它时,它实际上echo "X=$X" $X.

所以这个脚本打印了用cat myscript.sh | bash执行的 Hello World

#!/usr/bin/env bash
read X
hello world
echo "$X"
  • 使用 cat myscript.sh | bash 执行脚本有什么好处?为什么不做与我用./myscript.sh执行它相同的事情?
  • 如何避免 Bash 逐行执行,而是在 STDIN 到达末尾后执行所有行?

而不是只是运行

read X

。而是将其替换为...

read X </dev/tty || {
  X="some default because we can't read from the TTY here"
}

。如果要从控制台读取。当然,这只有在你有/dev/tty的情况下才有效,但如果你想做一些健壮的事情,你就不会从curl管道进入外壳。:)


当然,另一种选择是在命令行上传入X值。

curl https://some.place/with-untrusted-code-only-idiots-will-run-without-reading 
  | bash -s "value of X here"

。并在需要时参考脚本中的"$1" X

(顺便说一下,我当然希望你至少为此使用SSL,而不是建议人们运行他们通过纯HTTP下载的代码,没有带外验证步骤。当然,很多人都这样做,但这会使他们下载的网站 - 比如rvm.io - 成为大目标。大型、易于在中间人或 DNS 劫持的目标)。

当您cat脚本来抨击要执行的代码时,来自标准输入

read从哪里阅读?没错,这也是标准输入。这就是为什么你可以cat输入到接受标准输入的程序(如sedawk等)。

因此,当您执行此操作时,您本身并没有运行"脚本"。您正在运行一系列输入行。

您希望read在此设置中从何处读取数据?

您可以手动执行此操作(如果可以定义这样的位置)。或者,您可以像这样停止运行脚本。

最新更新