cd到目录并执行许多命令


10

我有以下脚本。

#!/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并执行一些命令。当未安装任何路径时,这第一次可以正常运行。但是,如果在某些路径上成功执行挂载后再运行它,它将无法继续,并在首次失败时停止。我希望所有命令都可以执行,即使由于“已经挂载”错误导致挂载失败。我怎样才能做到这一点?

还有没有比将所有这些命令组合在一起的更好的方法了?

Answers:


8

通过&&操作员在命令之间执行操作,每个命令将按顺序运行,并且如果任何命令失败(即返回非零状态),则不会执行后续命令。

如果您想继续进行下去,请使用;(或换行符,它等效)代替&&。在这里,您需要执行一个命令,如果执行成功,则无论是否成功,还要执行更多命令。实现此目的的一种方法是将这些命令放在大括号组内(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退出,运行sourceexport。” 那可能不是你的意思。/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

6

&&在这种情况下,分隔符表示“仅在最后一个命令成功后才继续”。如果您改用;命令,则无论结果如何,命令都将按顺序执行。

请注意,如果这是一项cron作业或对写入stderr的内容敏感的其他操作,则需要将错误重定向到/dev/null


您甚至不需要使用;。只需将每个命令放在自己的行上,但还必须摆脱set -e。如果您不关心命令失败,为什么还要使用set -e?(我知道这个问题只需要一行,但这在脚本中没有任何意义)。
camh 2013年

据推测,它不是脚本,而是要来源的(尽管有she-bang行没有意义),因为它设置为PS1。
斯特凡Chazelas

0

将命令放在方括号-()中,以便最后返回当前目录或cd-。如果将其放在文件中并运行:sh ./my_script.sh,它将在更改后的目录中运行命令。

cd  /mnt/gentoo
mount -t proc none /mnt/gentoo/proc
...
cd - 

重击

set -e 

将导致脚本在第一次失败时停止运行。因为您已设置+ e,所以我假设您希望脚本在命令失败时继续运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.