cd in una directory ed eseguire molti comandi


10

Ho seguito la sceneggiatura.

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

Quello che sto cercando di realizzare qui è cambiare in una directory /mnt/gentooed eseguire alcuni comandi. Funziona bene la prima volta quando nessuno dei percorsi è stato montato. Ma se lo eseguo dopo che il montaggio è stato eseguito con successo su alcuni percorsi, non continua e si interrompe al primo errore. Voglio che tutti i comandi vengano eseguiti anche se il montaggio non riesce a causa dell'errore "già montato". Come posso fare questo?

C'è anche un modo migliore che combinare tutti questi comandi insieme in una riga?

Risposte:


8

Con l' &&operatore tra i comandi, ciascun comando viene eseguito in sequenza e se un comando non riesce (ovvero restituisce uno stato diverso da zero), i comandi successivi non vengono eseguiti.

Se vuoi continuare, non importa cosa, usa ;(o una nuova riga, che è equivalente) invece di &&. Qui, è necessario eseguire un comando e, se ha esito positivo, eseguire altri comandi, sia che abbiano successo o meno. Un modo per ottenere ciò è inserire questi comandi all'interno di un gruppo di parentesi graffe (semplicemente cd … && mount1; mount2non funzionerà perché questo esegue mount2se ha cdesito positivo o meno a causa della precedenza).

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

In alternativa, uscire dallo script o tornare dalla funzione se cdfallisce.

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

In alternativa, esegui sotto set -ee metti || true("o continua comunque") dopo comandi che potrebbero non riuscire.

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

In alternativa, scrivi un comando che deve avere esito positivo: verifica se /proce così via sono già montati.

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

Hai un altro problema quando chiami chroot. Hai scritto: “corri bash nel chroot. Quando bash esce, corri sourcee export. " Probabilmente non è quello che intendevi. La lettura /etc/profilepuò essere fatta facendo bash una shell di login. Un possibile modo di impostare PS1potrebbe essere quello di impostarlo prima di eseguire bash, ma ciò non funzionerà se lo /etc/profilesovrascrive, il che è comune. Un modo migliore è impostata PS1in ~/.bashrc se esecuzione all'interno di una chroot ( .bashrcnon.profile ).

chroot . bash --login

Debian usa il seguente codice per impostare PS1in /etc/bash.bashrcbase al contenuto di /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\$ '

In alternativa, per il prompt, utilizzare invece una variabile di ambiente: run

CHROOT_LOCATION=$PWD chroot bash --login

e inseriscilo in ~/.bashrco /etc/bash.bashrc:

if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi

6

Il &&separatore in questo caso sta dicendo "continua solo se l'ultimo comando ha avuto successo". Se si utilizza ;invece, i comandi verranno eseguiti in sequenza indipendentemente dai risultati.

Nota che se questo è un lavoro cron o qualcos'altro sensibile alle cose che vengono scritte su stderr, dovrai reindirizzare gli errori /dev/null.


Non hai nemmeno bisogno di usare ;. Basta mettere ogni comando sulla propria riga, ma devi anche sbarazzarti di set -e. Se non ti interessa l'errore di comando, perché anche usarlo set -e? (Conosco la domanda posta per una riga, ma non ha senso all'interno di una sceneggiatura).
Cam

Presumibilmente, non è uno script ed è pensato per essere di provenienza (anche se avere una linea she-bang non ha senso allora) dato che si tratta di impostazioni PS1.
Stéphane Chazelas,

0

Metti il ​​comando tra parentesi - (), in modo da tornare alla directory corrente, o cd - alla fine. Se lo metti in un file ed eseguilo: sh ./my_script.sh eseguirà i comandi nella directory modificata in.

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

In bash

set -e 

causerà l'interruzione dell'esecuzione dello script al primo errore. Dato che hai impostato + e, suppongo che tu volessi che lo script continuasse a funzionare se un comando fallisce.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.