cd a un directorio y ejecutar muchos comandos

10

Tengo el siguiente guión.

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

Lo que estoy tratando de lograr aquí es cambiar a un directorio /mnt/gentooy ejecutar algunos comandos. Esto funciona bien la primera vez cuando no se montó ninguna ruta. Pero si lo ejecuto después de que el montaje se haya realizado con éxito en algunas rutas, no continúa y se detiene en el primer fallo. Quiero que todos los comandos se ejecuten incluso si el montaje falla debido a un error 'ya montado'. ¿Cómo puedo hacer esto?

¿También hay una mejor manera que combinar todos estos comandos en una sola línea?

Dilawar
fuente

Respuestas:

8

Con el &&operador entre comandos, cada comando se ejecuta en secuencia, y si algún comando falla (es decir, devuelve un estado distinto de cero), los comandos posteriores no se ejecutan.

Si desea continuar, pase lo que pase, use ;(o una nueva línea, que es equivalente) en lugar de &&. Aquí, debe ejecutar un comando, y si tiene éxito, ejecute algunos comandos más si tienen éxito o no. Una forma de lograr esto es colocar estos comandos dentro de un grupo de llaves (simplemente cd … && mount1; mount2no funcionará porque esto se ejecuta con éxito mount2o no cddebido a la precedencia).

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

Alternativamente, salga del script o regrese de la función si cdfalla.

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

Alternativamente, ejecute debajo set -ey coloque || true("o continúe de todos modos") después de los comandos que pueden fallar.

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

Alternativamente, escriba un comando que debe tener éxito: pruebe si /procy así sucesivamente ya están montados.

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

Tienes otro problema donde llamas chroot. Has escrito: “ejecuta bash en el chroot. Cuando bash salga, corre sourcey export. Eso probablemente no sea lo que quisiste decir. La lectura /etc/profilese puede hacer haciendo bash un shell de inicio de sesión. Una posible forma de configurarlo PS1puede ser configurarlo antes de ejecutar bash, pero eso no funcionará si lo /etc/profileanula, lo cual es común. Una mejor manera es a juego PS1en ~/.bashrc si se ejecuta dentro de un chroot ( .bashrcno.profile ).

chroot . bash --login

Debian utiliza el siguiente código para establecer PS1en /etc/bash.bashrcfunción del contenido 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\$ '

Alternativamente, para la solicitud, use una variable de entorno en su lugar: ejecutar

CHROOT_LOCATION=$PWD chroot bash --login

y poner esto en ~/.bashrco /etc/bash.bashrc:

if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi
Gilles 'SO- deja de ser malvado'
fuente
6

El &&separador en este caso dice 'continuar solo si el último comando fue exitoso'. Si usa ;en su lugar, los comandos se ejecutarán en secuencia independientemente de los resultados.

Tenga en cuenta que si se trata de un trabajo cron o algo más sensible a las cosas que se escriben en stderr, deberá redirigir los errores /dev/null.

Flup
fuente
Ni siquiera necesitas usar ;. Simplemente ponga cada comando en su propia línea, pero también debe deshacerse de él set -e. Si no te importa el fallo del comando, ¿por qué usarlo set -e? (Sé que la pregunta solicitó una línea, pero eso no tiene sentido dentro de un guión).
camh
Presumiblemente, no es un script y está destinado a ser obtenido (aunque tener una línea she-bang no tiene sentido entonces) ya que es la configuración PS1.
Stéphane Chazelas
0

Ponga el comando entre paréntesis - (), para que regrese al directorio actual, o cd - al final. Si coloca esto en un archivo y lo ejecuta: sh ./my_script.sh ejecutará los comandos en el directorio cambiado a.

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

En bash

set -e 

hará que el script deje de ejecutarse en el primer error. Debido a que ha configurado + e, supongo que desea que el script continúe ejecutándose si falla un comando.

Interrelacionado
fuente