如果我理解正确,您正在尝试做这样的事情:
#!/usr/bin/env bash
curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
echo "Why doesn't this run?"
echo "Do something else!"
但是最后两行没有执行,对吧?
简答
我能想到的几个解决方案:
-
使用进程替换运行带有 --noninteractive 标志的 oh-my-fish 安装程序:
fish <(curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install) --noninteractive
-
退出 oh-my-fish 通过 exit 或 Ctrl+Ctrl 创建的 fish shell -- bash 脚本的其余部分应在此时执行.
更多详情
问题是 oh-my-fish 安装脚本最后包含了这个“清理”部分:
# We made it!
say "Installation successful!"
# Open a brand new shell if we are in interactive mode.
set -q NONINTERACTIVE
or exec fish < /dev/tty
最后一行做了两件事:
-
exec 用新的 fish shell 替换安装程序运行的 fish shell,以便 oh-my-fish 可以在该 shell 实例中使用
-
< /dev/tty 强制新的 shell 开始从终端读取输入。没有这个,脚本将退出,返回到您的调用脚本。安装程序的开发人员不希望发生这种情况 - 他们希望新的 fish 实例在安装程序运行后与 oh-my-fish 一起“准备就绪”。
无论如何,这种组合将阻止任何“包含”脚本继续执行,直到新的 fish 实例终止。
您可以在MRE 中看到这一点:
test_exec.fish:
#!/usr/bin/fish
exec fish < /dev/tty
echo "This never runs"
wrapper.sh:
#!/usr/bin/env bash
cat test_exec.fish | fish
echo "Why doesn't this run?"
执行wrapper.sh 不会导致输出,因为test_exec.fish 创建了一个从终端读取的新fish 实例。
但是,如果您在运行./wrapper.sh 之后运行ps,您会看到幕后还有更多事情要做:
$ ps
PID TTY TIME CMD
1494 pts/1 00:00:00 fish
1751 pts/1 00:00:00 bash
1753 pts/1 00:00:00 fish
1904 pts/1 00:00:00 ps
第一个fish(pid 1494,供参考)是您开始的地方; bash 仍在运行 wrapper.sh 脚本;最后一个fish 是我们强制从/dev/tty 读取的一个读数,现在正在读取和执行ps。
如上所述,如果您使用exit 或Ctrl+Ctrl 退出最后一个fish,bash ./wrapper.sh 将继续运行,输出:
Why doesn't this run?
然后会自动退出脚本/bash,回到原来的fish(pid 1494):
$ ps
PID TTY TIME CMD
1494 pts/1 00:00:00 fish
1958 pts/1 00:00:00 ps
请注意,至少在我的系统上,tty 重定向会导致一些问题,例如需要使用终端 reset 命令更正的 Backspace 损坏。
或者,我们可以通过使用--noninteractive 标志调用安装程序来完全阻止exec fish < /dev/tty 运行。
要将标志传递给您正在下载的脚本,我们使用进程替换。这取代了:
curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
与
fish <(curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install) --noninteractive
请注意,如果您从 fish 脚本而不是 bash 脚本调用它,则语法为:
fish (curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | psub) --noninteractive