I just want to write a small script to automate my fish shell installation. Part of that installation includes calling the official omf oh-my-fish
installer script (curl ...).
#!/bin/bash
sudo apt update \
&& sudo apt install fish -y \
&& sudo chsh -s /usr/bin/fish \
&& curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish \
&& fish -c "omf install bira" \
&& echo -e "\nDone.\n"
Unfortunately, after the curl install command none of the following commands in my script are executed, it fails to continue. Does someone have an answer for this?
Update: Sorry for the inaccurate description of my problem. I've edited my question and I hope now everybody understands it better. If my description is still not good enough, please just tell me and I will edit it again.
If I understand you correctly, you are trying to do something like this:
#!/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!"
But the last two lines don't execute, right?
Several solutions that I can think of:
Run the oh-my-fish installer with the --noninteractive
flag using process substitution:
fish <(curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install) --noninteractive
Exit the fish shell that oh-my-fish creates by either exit
or Ctrl+Ctrl -- The remainder of your bash script should execute at that point.
The problem is that the oh-my-fish installation script includes this "clean-up" section at the end:
# 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
That final line does two things:
exec
replaces the fish shell that the installer is running in with a new fish
shell so that oh-my-fish is ready to use in that shell instance< /dev/tty
forces that new shell to start reading input from the terminal. Without this, the script would exit, returning to your calling script. The developer of the installer doesn't want this to happen - They want the new fish instance to be "ready to go" with oh-my-fish after the installer runs.Regardless, that combination will prevent any "containing" script from continuing to execute until the new fish instance is terminated.
You can see this in a bit of an 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?"
Executing wrapper.sh
results in no output, since the test_exec.fish
created a new fish
instance that reads from the terminal.
However, if you run ps
after running ./wrapper.sh
, you can see that there's more going on behind the scenes:
$ 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
The first fish
(pid 1494, for reference here) is where you started; the bash
is still running the wrapper.sh
script; and the last fish
is the one reading that we forced to read from /dev/tty
and is now reading and executing ps
.
As mentioned above, if you exit the last fish
with either exit
or Ctrl+Ctrl, bash ./wrapper.sh
will continue running, output:
Why doesn't this run?
It will then automatically exit the script/bash
and return to the original fish
(pid 1494):
$ ps
PID TTY TIME CMD
1494 pts/1 00:00:00 fish
1958 pts/1 00:00:00 ps
Note that, at least on my system, the tty
redirection causes some issues, such as broken Backspace that need to be corrected with a terminal reset
command.
Alternatively, we can prevent the exec fish < /dev/tty
from running at all by calling the installer with the --noninteractive
flag.
To pass a flag to the script that you are downloading, we use process substitution. This replaces:
curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
with
fish <(curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install) --noninteractive
Note that if you were calling this from a fish
script, instead of a bash
script, the syntax would be:
fish (curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | psub) --noninteractive