다음 스크립트가 있습니다.
#!/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"
여기서 달성하려는 작업은 디렉터리를 변경 /mnt/gentoo
하고 몇 가지 명령을 실행하는 것입니다. 경로가 마운트되지 않은 처음에는 제대로 작동합니다. 그러나 특정 경로에서 성공적으로 설치한 후 실행하면 계속되지 않고 첫 번째 실패 시 중지됩니다. "이미 설치됨" 오류로 인해 설치가 실패하더라도 모든 명령이 실행되기를 원합니다. 어떻게 해야 하나요?
이 모든 명령을 함께 결합하는 것보다 더 좋은 방법은 무엇일까요?
답변1
명령 사이에 연산자를 사용하면 &&
각 명령이 순서대로 실행되며 명령이 실패하면(즉, 0이 아닌 상태를 반환하는 경우) 후속 명령이 실행되지 않습니다.
어쨌든 계속하려면 ;
대신 (또는 이에 상응하는 줄 바꿈)을 사용하십시오 &&
. 여기서 명령을 실행해야 하며, 성공하면 성공 또는 실패에 관계없이 몇 가지 명령을 더 실행해야 합니다. 이를 달성하는 한 가지 방법은 이러한 명령을 중괄호 그룹에 넣는 것입니다( 우선 순위로 인해 성공 여부에 관계없이 명령이 실행되기 cd … && mount1; mount2
때문에 작동하지 않습니다 ).mount2
cd
cd /mnt/gentoo && {
mount -t proc none /mnt/gentoo/proc
mount --rbind /dev /mnt/gentoo/dev
mount --rbind /sys /mnt/gentoo/sys
…
}
또는 실패하면 스크립트를 종료하거나 함수에서 돌아갑니다 cd
.
cd /mnt/gentoo || exit $?
mount -t proc none /mnt/gentoo/proc
…
또는 아래에서 실행 set -e
하고 || true
실패할 수 있는 명령 뒤에 넣습니다("또는 계속 진행").
set -e
cd /mnt/gentoo
mount -t proc none /mnt/gentoo/proc || true
…
또는 성공해야 하는 명령을 작성합니다. /proc
설치되었는지 테스트하는 등의 작업을 수행합니다.
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
에 전화하시면 또 다른 문제가 발생합니다 chroot
. "chroot에서 bash를 실행하세요. bash가 종료되면 실행 source
하고 ." 라고 작성하셨습니다. export
아마도 그런 뜻이 아닐 것입니다. /etc/profile
bash를 로그인 쉘로 설정하여 읽기를 수행할 수 있습니다. 이를 설정하는 한 가지 가능한 방법 PS1
은 bash를 실행하기 전에 설정하는 것이지만, 덮어쓰면 작동하지 않는 /etc/profile
것이 일반적입니다. 더 나은 접근 방식 PS1
은~/.bashrc
chroot 내에서 실행 중인 경우(.bashrc
, 아니요.profile
).
chroot . bash --login
데비안은 다음 코드를 사용하여 다음 PS1
과 같이 설정합니다./etc/bash.bashrc
/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\$ '
또는 프롬프트의 경우 대신 환경 변수를 사용하십시오.
CHROOT_LOCATION=$PWD chroot bash --login
그것을 넣거나 ~/.bashrc
:/etc/bash.bashrc
if [ -n "$CHROOT_LOCATION" ]; then PS1="($CHROOT_LOCATION)$PS1"; fi
답변2
이 예에서 구분 기호는 &&
"마지막 명령이 성공한 경우에만 계속"을 의미합니다. 대신 사용 하면 ;
결과에 관계없이 명령이 순차적으로 실행됩니다.
cron 작업이거나 stderr에 기록된 내용에 민감한 다른 작업인 경우 오류를 로 리디렉션해야 합니다 /dev/null
.
답변3
현재 디렉터리로 돌아가려면 명령을 대괄호 - ()로 묶거나 끝에 cd -로 묶습니다. 이것을 파일에 넣고 실행하면: sh ./my_script.sh 변경된 디렉토리에서 명령이 실행됩니다.
cd /mnt/gentoo
mount -t proc none /mnt/gentoo/proc
...
cd -
배쉬에서
set -e
첫 번째 실패 시 스크립트 실행이 중지됩니다. +e를 설정했으므로 명령이 실패하더라도 스크립트가 계속 실행되기를 원한다고 가정합니다.