我有以下脚本。
#!/bin/bash
mount /dev/sda6 /mnt/gentoo
set +e
cd /mnt/gentoo && mount -t proc none /mnt/gentoo/proc \
&& mount --rbind /dev /mnt/gentoo/dev \
&& mount --rbind /sys /mnt/gentoo/sys \
&& chroot /mnt/gentoo /bin/bash \
&& source /etc/profile \
&& export PS1="(chroot)$PS1"
我在这里想要完成的是更改到一个目录/mnt/gentoo
并执行一些命令。当没有安装任何路径时,第一次可以正常工作。但是,如果我在某些路径上成功执行安装后运行它,它不会继续并在第一次失败时停止。即使安装由于“已安装”错误而失败,我也希望执行所有命令。我怎样才能做到这一点?
还有比将所有这些命令组合在一起更好的方法吗?
答案1
通过&&
命令之间的运算符,每个命令都会按顺序运行,如果任何命令失败(即返回非零状态),则后续命令不会执行。
如果您无论如何都想继续,请使用;
(或等效的换行符)而不是&&
.这里,你需要执行一个命令,如果成功了,再执行一些命令,不管成功与否。实现此目的的一种方法是将这些命令放在大括号组中(只是cd … && mount1; mount2
不起作用,因为mount2
无论cd
由于优先级是否成功,该命令都会执行)。
cd /mnt/gentoo && {
mount -t proc none /mnt/gentoo/proc
mount --rbind /dev /mnt/gentoo/dev
mount --rbind /sys /mnt/gentoo/sys
…
}
或者,如果失败,则退出脚本或从函数返回cd
。
cd /mnt/gentoo || exit $?
mount -t proc none /mnt/gentoo/proc
…
或者,在 下运行set -e
,并将|| true
(“或继续前进”)放在可能失败的命令后面。
set -e
cd /mnt/gentoo
mount -t proc none /mnt/gentoo/proc || true
…
或者,编写一个必须成功的命令:测试是否/proc
已安装等等。
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
您致电时遇到另一个问题chroot
。您已经写道:“在 chroot 中运行 bash。当 bash 退出时,运行source
并export
。”这可能不是你的意思。/etc/profile
可以通过将 bash 设置为登录 shell 来完成读取。一种可能的设置方法PS1
是在运行 bash 之前设置它,但如果覆盖它,则不会起作用/etc/profile
,这很常见。更好的方法是PS1
设置~/.bashrc
如果在 chroot 内运行(.bashrc
, 不是.profile
)。
chroot . bash --login
Debian根据 的内容使用以下代码进行PS1
设置:/etc/bash.bashrc
/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\$ '
或者,对于提示符,请改用环境变量:运行
CHROOT_LOCATION=$PWD chroot bash --login
并将其放入~/.bashrc
或/etc/bash.bashrc
:
if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi
答案2
本例中的分隔&&
符表示“仅当最后一个命令成功时才继续”。如果您;
改为使用,命令将按顺序执行,无论结果如何。
请注意,如果这是一个 cron 作业或其他对写入 stderr 的内容敏感的内容,则需要将错误重定向到/dev/null
.
答案3
将命令放在括号 - () 中,以便返回当前目录,或者在末尾 cd - 。如果将其放入文件中并运行它: sh ./my_script.sh 它将运行更改为目录中的命令。
cd /mnt/gentoo
mount -t proc none /mnt/gentoo/proc
...
cd -
在bash中
set -e
将导致脚本在第一次失败时停止运行。因为您已经设置了 +e,所以我假设您希望脚本在命令失败时继续运行。