cd dans un répertoire et exécutez de nombreuses commandes

10

J'ai le script suivant.

#!/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" 

Ce que j'essaie d'accomplir ici, c'est de passer à un répertoire /mnt/gentooet d'exécuter quelques commandes. Cela fonctionne bien la première fois quand aucun des chemins n'a été monté. Mais si je l'exécute après que le montage a été effectué avec succès sur certains chemins, il ne continue pas et s'arrête à la première défaillance. Je veux que toutes les commandes soient exécutées même si le montage échoue en raison d'une erreur «déjà monté». Comment puis-je faire ceci?

Y a-t-il également un meilleur moyen que de combiner toutes ces commandes ensemble sur une seule ligne?

Dilawar
la source

Réponses:

8

Avec l' &&opérateur entre les commandes, chaque commande s'exécute en séquence et si une commande échoue (c.-à-d. Renvoie un état différent de zéro), les commandes suivantes ne sont pas exécutées.

Si vous voulez continuer quoi qu'il arrive, utilisez ;(ou une nouvelle ligne, qui est équivalente) au lieu de &&. Ici, vous devez exécuter une commande, et si elle réussit, exécutez d'autres commandes, qu'elles réussissent ou non. Une façon d'y parvenir est de placer ces commandes à l'intérieur d'un groupe d'accolades ( cd … && mount1; mount2ne fonctionnera tout simplement pas car cela s'exécute, mount2qu'il cdréussisse ou non en raison de la priorité).

cd /mnt/gentoo && {
  mount -t proc none /mnt/gentoo/proc
  mount --rbind /dev /mnt/gentoo/dev
  mount --rbind /sys /mnt/gentoo/sys
  
}

Sinon, quittez le script ou revenez de la fonction en cas d' cdéchec.

cd /mnt/gentoo || exit $?
mount -t proc none /mnt/gentoo/proc

Sinon, exécutez under set -eet mettez || true(«ou continuez quand même») après les commandes qui peuvent échouer.

set -e
cd /mnt/gentoo
mount -t proc none /mnt/gentoo/proc || true

Sinon, écrivez une commande qui doit réussir: testez si /procet ainsi de suite sont déjà montés.

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

Vous avez un autre problème où vous appelez chroot. Vous avez écrit: «lancez bash dans le chroot. Lorsque bash se termine, exécutez sourceet export". Ce n'est probablement pas ce que vous vouliez dire. La lecture /etc/profilepeut être effectuée en faisant de bash un shell de connexion. Un moyen possible de définir PS1peut être de le définir avant d'exécuter bash, mais cela ne fonctionnera pas s'il le /etc/profileremplace, ce qui est courant. Une meilleure façon est de mettre PS1en ~/.bashrc cas d' exécution à l' intérieur d' un chroot ( .bashrcnon.profile ).

chroot . bash --login

Debian utilise le code suivant pour s'installer PS1en /etc/bash.bashrcfonction du contenu de /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\$ '

Sinon, pour l'invite, utilisez une variable d'environnement à la place: exécutez

CHROOT_LOCATION=$PWD chroot bash --login

et mettez-le dans ~/.bashrcou /etc/bash.bashrc:

if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi
Gilles 'SO- arrête d'être méchant'
la source
6

Dans &&ce cas, le séparateur dit "ne continuer que si la dernière commande a réussi". Si vous utilisez à la ;place, les commandes s'exécuteront en séquence indépendamment des résultats.

Notez que s'il s'agit d'un travail cron ou de quelque chose d'autre sensible aux choses écrites sur stderr, vous devrez rediriger les erreurs vers /dev/null.

Flup
la source
Vous n'avez même pas besoin d'utiliser ;. Mettez simplement chaque commande sur sa propre ligne, mais vous devez également vous débarrasser de set -e. Si vous ne vous souciez pas de l'échec de la commande, pourquoi même l'utiliser set -e? (Je connais la question posée pour une ligne, mais cela n'a aucun sens dans un script).
camh
Vraisemblablement, ce n'est pas un script et est censé provenir (bien qu'avoir une ligne de she-bang n'a pas de sens alors) car ce sont les paramètres PS1.
Stéphane Chazelas
0

Mettez la commande entre crochets - (), de sorte que vous reveniez au répertoire courant, ou cd - à la fin. Si vous mettez cela dans un fichier et l'exécutez: sh ./my_script.sh, il exécutera les commandes dans le répertoire changé en.

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

En bash

set -e 

entraînera l'arrêt du script lors du premier échec. Parce que vous avez défini + e, je suppose que vous souhaitez que le script continue de fonctionner si une commande échoue.

Interlated
la source