cd do katalogu i wykonaj wiele poleceń

10

Mam następujący skrypt.

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

Usiłuję tutaj przejść do katalogu /mnt/gentooi wykonać kilka poleceń. Działa to ok za pierwszym razem, gdy żadna ścieżka nie została zamontowana. Ale jeśli uruchomię go po pomyślnym wykonaniu montażu na niektórych ścieżkach, nie będzie kontynuowane i zatrzyma się przy pierwszej awarii. Chcę, aby wszystkie polecenia były wykonywane, nawet jeśli montowanie kończy się niepowodzeniem z powodu błędu „już zamontowanego”. W jaki sposób mogę to zrobić?

Czy jest też lepszy sposób niż połączenie wszystkich tych poleceń razem w jednym wierszu?

Dilawar
źródło

Odpowiedzi:

8

Z &&operatorem między poleceniami, każde polecenie uruchamia się w sekwencji, a jeśli którekolwiek polecenie zakończy się niepowodzeniem (tj. Zwraca niezerowy status), kolejne polecenia nie zostaną wykonane.

Jeśli chcesz kontynuować bez względu na wszystko, użyj ;(lub nowej linii, która jest równoważna) zamiast &&. Tutaj musisz wykonać jedno polecenie, a jeśli się powiedzie, wykonaj kilka kolejnych poleceń, niezależnie od tego, czy się powiedzie. Jednym ze sposobów na osiągnięcie tego jest umieszczenie tych poleceń w grupie nawiasów klamrowych (po prostu cd … && mount1; mount2nie zadziała, ponieważ spowoduje to, mount2czy cduda się z powodu pierwszeństwa).

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

Ewentualnie wyjdź ze skryptu lub powróć z funkcji, jeśli się cdnie powiedzie.

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

Alternatywnie, biegnij pod set -ei wstaw || true(„lub idź dalej”) po poleceniach, które mogą się nie powieść.

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

Możesz też napisać polecenie, które musi się powieść: sprawdź, czy /proci tak jest już zamontowane.

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

Masz inny problem, gdy dzwonisz chroot. Napisałeś: „uruchom bash w chroot. Kiedy bash zakończy działanie, uruchom sourcei export. ” Prawdopodobnie nie o to ci chodziło. Czytanie /etc/profilemożna wykonać, czyniąc bash powłoką logowania. Możliwym sposobem ustawienia PS1może być ustawienie go przed uruchomieniem bash, ale to nie zadziała, jeśli /etc/profilezastąpi to, co jest powszechne. Lepszym sposobem jest ustawienie PS1w ~/.bashrc razie działa wewnątrz chroot ( .bashrcnie.profile ).

chroot . bash --login

Debian używa następującego kodu do ustawienia PS1na /etc/bash.bashrcpodstawie zawartości /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\$ '

Alternatywnie, w wierszu polecenia zamiast tego użyj zmiennej środowiskowej: uruchom

CHROOT_LOCATION=$PWD chroot bash --login

i wstaw to ~/.bashrclub /etc/bash.bashrc:

if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi
Gilles „SO- przestań być zły”
źródło
6

W &&tym przypadku separator mówi „kontynuuj tylko, jeśli ostatnie polecenie zakończyło się powodzeniem”. Jeśli użyjesz ;zamiast tego, polecenia będą wykonywane po kolei, niezależnie od wyników.

Zauważ, że jeśli jest to zadanie cron lub coś innego wrażliwego na rzeczy zapisywane do stderr, musisz przekierować błędy /dev/null.

Flup
źródło
Nie musisz nawet używać ;. Po prostu umieść każde polecenie w osobnej linii, ale musisz się go również pozbyć set -e. Jeśli nie obchodzi Cię błąd polecenia, po co w ogóle korzystać set -e? (Znam pytanie zadane dla jednej linii, ale nie ma to sensu w skrypcie).
camh
Przypuszczalnie nie jest to skrypt i ma być pozyskiwany (choć wtedy nie ma sensu mieć linii she-bang), ponieważ ma ustawienia PS1.
Stéphane Chazelas,
0

Umieść polecenie w nawiasach - (), aby powrócić do bieżącego katalogu lub cd - na końcu. Jeśli umieścisz to w pliku i uruchomisz: sh ./my_script.sh, uruchomi polecenia w katalogu zmienionym na.

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

W bash

set -e 

spowoduje, że skrypt przestanie działać przy pierwszej awarii. Ponieważ ustawiłeś + e, zakładam, że chcesz, aby skrypt działał, jeśli polecenie się nie powiedzie.

Interlated
źródło