ディレクトリに移動し、多くのコマンドを実行します


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に移動していくつかのコマンドを実行することです。これは、パスがマウントされていないときに初めて正常に機能します。ただし、一部のパスでマウントが正常に実行された後に実行すると、継続せず、最初の失敗で停​​止します。「すでにマウントされています」エラーが原因でマウントが失敗した場合でも、すべてのコマンドを実行してください。これどうやってするの?

また、これらすべてのコマンドを1行にまとめるよりも良い方法はありますか?

回答:


8

&&コマンド間の演算子を使用すると、各コマンドは順番に実行され、コマンドが失敗した場合(つまり、ゼロ以外のステータスを返した場合)、後続のコマンドは実行されません。

どうしても続けたい場合;は、の代わりに(または同等の改行)を使用します&&。ここでは、1つのコマンドを実行する必要があり、成功した場合は、成功したかどうかに関係なく、さらにいくつかのコマンドを実行します。これを実現する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が終了したら、とを実行sourceexportます。」それはおそらくあなたが意図したものではありません。読み取り/etc/profileは、bashをログインシェルにすることで実行できます。設定する可能性のある方法は、PS1bashを実行する前に設定することです/etc/profileが、それをオーバーライドすると機能しなくなります。これは一般的です。より良い方法は、(ではなくchroot内で実行PS1する~/.bashrc 場合に設定することです.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


を使用する必要さえありません;。各コマンドを1行に入力するだけですが、も削除する必要がありset -eます。コマンドの失敗を気にしない場合は、なぜ使用するのset -eですか?(私は質問が1行を要求したことを知っていますが、それはスクリプト内では意味がありません)。
camh 2013年

おそらく、それはスクリプトではなく、PS1の設定であるため、ソースを提供することを目的としています(ただし、シバンの線は意味がありません)。
ステファンChazelas

0

コマンドを角かっこ(-)に入れて、現在のディレクトリに戻るか、最後にcd-にします。これをファイルに入れて実行すると、sh ./my_script.shは、変更されたディレクトリでコマンドを実行します。

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

バッシュで

set -e 

最初の失敗時にスクリプトの実行を停止します。+ eを設定したので、コマンドが失敗した場合にスクリプトを実行し続けたいと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.