cd vào một thư mục và thực hiện nhiều lệnh


10

Tôi có kịch bản sau đây.

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

Những gì tôi đang cố gắng thực hiện ở đây là thay đổi một thư mục /mnt/gentoovà thực thi một vài lệnh. Điều này hoạt động tốt lần đầu tiên khi không có con đường nào được gắn kết. Nhưng nếu tôi chạy nó sau khi cài đặt đã được thực hiện thành công trên một số đường dẫn, nó không tiếp tục và dừng lại ở lần thất bại đầu tiên. Tôi muốn tất cả các lệnh được thực thi ngay cả khi mount bị lỗi do lỗi 'đã được gắn'. Tôi có thể làm cái này như thế nào?

Ngoài ra có cách nào tốt hơn là kết hợp tất cả các lệnh này lại với nhau trong một dòng không?

Câu trả lời:


8

Với &&toán tử giữa các lệnh, mỗi lệnh chạy theo trình tự và nếu bất kỳ lệnh nào bị lỗi (tức là trả về trạng thái khác không), các lệnh tiếp theo sẽ không được thực thi.

Nếu bạn muốn tiếp tục đi bất kể điều gì, hãy sử dụng ;(hoặc một dòng mới, tương đương) thay vì &&. Tại đây, bạn cần thực thi một lệnh và nếu nó thành công, hãy thực thi thêm một số lệnh cho dù chúng có thành công hay không. Một cách để đạt được điều này là đặt các lệnh này trong một nhóm niềng răng (chỉ cd … && mount1; mount2không hoạt động vì điều này thực thi mount2cdthành công hay không do ưu tiên).

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

Hoặc, thoát khỏi tập lệnh hoặc trả về từ chức năng nếu cdthất bại.

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

Ngoài ra, hãy chạy bên dưới set -evà đặt || true(Tuy nhiên hoặc tiếp tục đi bằng cách nào đó) sau khi các lệnh có thể thất bại.

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

Ngoài ra, viết một lệnh phải thành công: kiểm tra nếu /procvà như vậy đã được gắn kết.

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

Bạn có một vấn đề khác mà bạn gọi chroot. Bạn đã viết: Quảng cáo chạy bash trong chroot. Khi bash thoát, chạy sourceexport. Đó có lẽ không phải là ý bạn. Đọc /etc/profilecó thể được thực hiện bằng cách làm cho bash một vỏ đăng nhập. Một cách có thể để thiết lập PS1có thể là đặt nó trước khi chạy bash, nhưng nó sẽ không hoạt động nếu /etc/profileghi đè lên nó, điều này là phổ biến. Cách tốt hơn là để thiết lập PS1trong ~/.bashrc nếu chạy bên trong một chroot ( .bashrckhông.profile ).

chroot . bash --login

Debian sử dụng đoạn mã sau để thiết lập PS1trong /etc/bash.bashrcdựa trên nội dung của /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\$ '

Ngoài ra, để nhắc, sử dụng biến môi trường thay thế: chạy

CHROOT_LOCATION=$PWD chroot bash --login

và đặt cái này vào ~/.bashrchoặc /etc/bash.bashrc:

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

6

Dấu &&phân cách trong trường hợp này là 'chỉ tiếp tục nếu lệnh cuối cùng thành công'. Nếu bạn sử dụng ;thay thế, các lệnh sẽ thực hiện theo trình tự bất kể kết quả.

Lưu ý rằng nếu đây là công việc định kỳ hoặc thứ gì đó nhạy cảm với nội dung được ghi vào thiết bị lỗi chuẩn, bạn sẽ cần chuyển hướng các lỗi sang /dev/null.


Bạn thậm chí không cần sử dụng ;. Chỉ cần đặt mỗi lệnh trên dòng riêng của nó, nhưng bạn cũng phải thoát khỏi set -e. Nếu bạn không quan tâm đến lỗi lệnh, tại sao thậm chí sử dụng set -e? (Tôi biết câu hỏi yêu cầu một dòng, nhưng điều đó không có ý nghĩa trong một kịch bản).
CAMH

Có lẽ, đó không phải là một kịch bản và có nghĩa là có nguồn gốc (mặc dù có một dòng cô ấy không có ý nghĩa gì) vì nó cài đặt PS1.
Stéphane Chazelas

0

Đặt lệnh trong ngoặc - (), để bạn quay lại thư mục hiện tại hoặc cd - ở cuối. Nếu bạn đặt nó trong một tệp và chạy nó: sh ./my_script.sh nó sẽ chạy các lệnh trong thư mục đã thay đổi.

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

Trong bash

set -e 

sẽ khiến tập lệnh ngừng chạy trong lần thất bại đầu tiên. Vì bạn đã đặt + e nên tôi cho rằng bạn muốn tập lệnh tiếp tục chạy nếu một lệnh thất bại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.