cd para um diretório e execute muitos comandos

10

Eu tenho o seguinte script.

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

O que estou tentando realizar aqui é mudar para um diretório /mnt/gentooe executar alguns comandos. Isso funciona bem na primeira vez em que nenhum caminho foi montado. Mas se eu executá-lo após a montagem ter sido realizada com êxito em alguns caminhos, ele não continua e para na primeira falha. Eu quero que todos os comandos sejam executados, mesmo que a montagem esteja falhando devido ao erro 'já montado'. Como posso fazer isso?

Também existe uma maneira melhor do que combinar todos esses comandos juntos em uma linha?

Dilawar
fonte

Respostas:

8

Com o &&operador entre os comandos, cada comando é executado em sequência e, se algum comando falhar (ou seja, retorna um status diferente de zero), os comandos subseqüentes não são executados.

Se você quiser continuar, não importa o quê, use ;(ou uma nova linha, que é equivalente) em vez de &&. Aqui, você precisa executar um comando e, se for bem-sucedido, execute mais alguns comandos, sejam eles bem-sucedidos ou não. Uma maneira de conseguir isso é colocar esses comandos dentro de um grupo de chaves (simplesmente cd … && mount1; mount2não funcionará porque isso executa mount2se é ou não cdbem-sucedido devido à precedência).

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

Como alternativa, saia do script ou retorne da função se cdfalhar.

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

Como alternativa, execute sob set -ee coloque || true("ou continue assim mesmo") após os comandos que podem falhar.

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

Como alternativa, escreva um comando que deve ter êxito: teste se /procjá está montado.

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

Você tem outro problema onde liga chroot. Você escreveu: “execute bash no chroot. Quando o bash sair, corra sourcee export. ” Provavelmente não foi isso que você quis dizer. A leitura /etc/profilepode ser feita tornando o bash um shell de login. Uma maneira possível de configurar PS1pode ser configurá-lo antes de executar o bash, mas isso não funcionará se o /etc/profilesubstituir, o que é comum. A melhor maneira é definir PS1em ~/.bashrc se estiver rodando dentro de um chroot ( .bashrcnão.profile ).

chroot . bash --login

O Debian usa o seguinte código para configurar PS1com /etc/bash.bashrcbase no conteúdo 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\$ '

Como alternativa, para o prompt, use uma variável de ambiente: run

CHROOT_LOCATION=$PWD chroot bash --login

e coloque isso em ~/.bashrcou /etc/bash.bashrc:

if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi
Gilles 'SO- parar de ser mau'
fonte
6

O &&separador neste caso está dizendo 'continue apenas se o último comando tiver sido bem-sucedido'. Se você usar ;, os comandos serão executados em sequência, independentemente dos resultados.

Observe que, se este é um trabalho cron ou algo mais sensível a coisas que estão sendo gravadas no stderr, você precisará redirecionar os erros para /dev/null.

Flup
fonte
Você nem precisa usar ;. Basta colocar cada comando em sua própria linha, mas você também precisa se livrar do set -e. Se você não se importa com a falha do comando, por que usar set -e? (Eu sei que a pergunta fez uma linha, mas isso não faz sentido em um script).
Camh
Presumivelmente, não é um script e deve ser adquirido (embora ter uma linha she-bang não faça sentido na época), pois está nas configurações do PS1.
Stéphane Chazelas 13/03/2013
0

Coloque o comando entre colchetes - (), para retornar ao diretório atual ou cd - no final. Se você colocar isso em um arquivo e executá-lo: sh ./my_script.sh, ele executará os comandos no diretório alterado para.

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

Na festança

set -e 

fará com que o script pare de executar na primeira falha. Como você configurou + e, eu assumiria que você desejava que o script continuasse sendo executado se um comando falhar.

Interlated
fonte