Cách khởi động lại hoàn toàn tập lệnh từ bên trong tập lệnh


22

Tôi đang thiết lập một tập lệnh shell với các mối đe dọa và các mối đe dọa phụ, các tùy chọn, v.v. Nhưng trên mỗi menu / menu con / vv, tôi cần một lựa chọn "Quay trở lại menu chính".

Tôi đã thiết lập menu và nó hoạt động tốt, nhưng tôi cần một cách đơn giản để khởi động lại tập lệnh từ đầu, đặt lại tất cả các biến, v.v.

Hoặc một cách để thoát khỏi tập lệnh hiện tại và bắt đầu lại.

Tôi đã cố gắng làm điều này:

ScriptLoc=$(readlink -f "$0")
./ScriptLoc

Nhưng điều đó bắt đầu tập lệnh "mới" bên trong tập lệnh "cũ", vì vậy khi tôi thoát tập lệnh "mới", nó sẽ quay trở lại tập lệnh "cũ" (nếu điều đó có ý nghĩa gì). Đó là một kịch bản bên trong một loại kịch bản.

Bất cứ ai cũng có một ý tưởng làm thế nào để khởi động lại nó hoàn toàn?


Đó nên là $ScriptLocdù sao đi nữa: ./ScriptLocngoại hình cho một kịch bản của tên đó trong thư mục hiện hành.
poolie

Câu trả lời:



10

Bạn có thể sử dụng một cái gì đó như thế này:

$(basename $0) && exit

$(basename $0)sẽ tạo một phiên bản mới của tập lệnh hiện tại và exitsẽ thoát khỏi phiên bản hiện tại của tập lệnh.

Đây là một kịch bản thử nghiệm làm nổi bật phương pháp trên:

#!/bin/bash

if ! [[ $count =~ ^[0-9]+$ ]] ; then
    export count=0
fi

echo $count

if [ $count -le 10 ]; then
    count=$(echo "$count+1" | bc)   
    ./$(basename $0) && exit #this will run if started from the same folder
fi

echo "This will be printed only when the tenth instance of script is reached"

Nếu bạn không sử dụng export count=0( countbiến thành biến môi trường) và chỉ sử dụng count=0(tạo contbiến biến tập lệnh cục bộ), thì tập lệnh sẽ không bao giờ dừng.


&& exitsẽ chỉ thoát nếu tập lệnh thành công. Vì vậy, nếu ví dụ tập lệnh không được thực thi hoặc có lỗi cú pháp, thì điều này có khả năng chỉ là quay.
poolie

Đã thêm ./ vào tên cơ sở - nếu không thì là một giải pháp đẹp - thực sự rất hay, def +1.
Lefty G Balogh

4

Đáng tin cậy để có được kịch bản hiện đang thực thi là khó hơn bạn nghĩ. Xem http://mywiki.wooledge.org/BashFAQ/028 .

Thay vào đó, bạn có thể làm một cái gì đó như thế này:

main_menu() { 
    printf '1. Do something cool\n'
    printf '2. Do something awesome\n'
    : ... etc
}

some_sub_sub_menu() {
    ...
    printf 'X. Return to main menu\n'
    ...
    if [[ $choice = [Xx] ]]; then
        exit 255
    fi
}

while true; do
    (main_menu)
    res=$?
    if (( res != 255 )); then
        break
    fi
done

Về cơ bản, bạn chạy hàm main_menu trong một lớp con, vì vậy nếu bạn thoát khỏi hàm main_menu hoặc bất kỳ menu phụ nào, bạn thoát khỏi lớp con, không phải lớp vỏ chính. trạng thái thoát 255 được chọn ở đây có nghĩa là "đi lại". Bất kỳ trạng thái thoát nào khác sẽ thoát ra khỏi vòng lặp vô hạn khác.

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.