With the && operator between commands, each command runs in sequence, and if any command fails (i.e. returns a nonzero status), the subsequent commands are not executed.
If you want to keep going no matter what, use ; (or a newline, which is equivalent) instead of &&. Here, you need to execute one command, and if it succeeds, execute some more commands whether they succeed or not. One way to achieve this is to put these commands inside a brace group (just cd … && mount1; mount2 won't work because this executes mount2 whether or not cd succeeds due to precedence).
cd /mnt/gentoo && {
mount -t proc none /mnt/gentoo/proc
mount --rbind /dev /mnt/gentoo/dev
mount --rbind /sys /mnt/gentoo/sys
…
}
Alternatively, exit the script or return from the function if cd fails.
cd /mnt/gentoo || exit $?
mount -t proc none /mnt/gentoo/proc
…
Alternatively, run under set -e, and put || true (“or keep going anyway”) after commands that may fail.
set -e
cd /mnt/gentoo
mount -t proc none /mnt/gentoo/proc || true
…
Alternatively, write a command that must succeed: test if /proc and so on are mounted already.
mount_if_needed () {
eval "mount_point=${\$#}"
awk -v target="$mount_point" '$2 == target {exit(0)} END {exit(1)}' </proc/mounts ||
mount "$@"
}
set -e
cd /mnt/gentoo
mount_if_needed -t proc none /mnt/gentoo/proc
You have another problem where you call chroot. You've written: “run bash in the chroot. When bash exits, run source and export.” That is probably not what you meant. Reading /etc/profile can be done by making bash a login shell. A possible way to set PS1 may be to set it before running bash, but that won't work if /etc/profile overrides it, which is common. A better way is to set PS1 in ~/.bashrc if running inside a chroot (.bashrc, not .profile).
chroot . bash --login
Debian uses the following code to set PS1 in /etc/bash.bashrc based on the content of /etc/debian_chroot:
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
Alternatively, for the prompt, use an environment variable instead: run
CHROOT_LOCATION=$PWD chroot bash --login
and put this in ~/.bashrc or /etc/bash.bashrc:
if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi