同时读取输入并通过stdin管道运行脚本

3

我有一个简单的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到达末尾后执行所有行?

3
为什么不使用 bash ./myscript.sh - anubhava
2
或者只需运行 ./myscript.sh - Karoly Horvath
1
因为实际上它更加复杂。我想编写一个简单的安装程序,使用 curl 下载一个 shell 脚本,然后将其传输到 bash 中,以避免创建临时文件,就像 Composer 在 PHP 中所做的那样(https://getcomposer.org/download/)。但是,如果这种方式不起作用,我还需要使用 PHP 或临时文件来完成。 - TheFox
@KarolyHorvath,你其实不需要知道我为什么要这样做。我想以这种方式来做。如果我会用 bash ./myscript.sh 或者 ./myscript.sh 来完成它,我也不会问了。 - TheFox
2
@TheFox 知道某人为什么提出问题有助于确定他们是否在问正确的问题。你想做什么和你应该做什么有时是两回事。 - chepner
显示剩余8条评论
2个回答

8

不仅仅是运行

read X

...代替它使用...

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

如果您想从控制台读取内容,可以使用以下代码。当然,这仅在您有/dev/tty的情况下才有效,但如果您想要做一些稳健的操作,您不会将curl导入shell中。:)


另一种选择是通过命令行传递您的X值。

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

当你需要X时,在你的脚本中引用"$1"

(顺便提一句,我真心希望你至少使用SSL,而不是建议人们在没有外部验证步骤的情况下通过普通HTTP运行下载的代码。许多人这样做,但这会使他们从中下载的网站(如rvm.io)成为重要目标。成为非常易受人为干扰和DNS劫持的目标)。


1
当你在bash中使用cat命令执行脚本时,要执行的代码来自于标准输入。 read命令从哪里读取数据呢?没错,也是从标准输入。这就是为什么你可以将输入内容通过cat命令传递给需要标准输入的程序(比如sedawk等)。
因此,当你这样做时,并不是在运行“一个脚本”,而是在运行一系列输入行。
在这种设置下,你希望read从哪里读取数据呢?
你可以手动指定(如果你能定义这样的位置)。或者你可以停止以这种方式运行你的脚本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接